microservices structure in Laravel with aws lambda - php

I am new to microservices, I only know the theory, developed some local examples, and also deploy them to AWS, but just that, and I have a project that has to be done with microservices, but my question is about the structure.
For example, I am planning to do the following:
Vuejs SPA for the frontend store in AWS S3- this will make the request to the Main Laravel app
the Main Laravel app to manage the authorization(login, register, password recovery)
When the user is logged in, is redirected to the "posts" page and that page loads all the posts, you can create new posts, delete them, add comments, etc. This would be another Laravel app, another microservice
Then I have another Laravel app for the user profile, where the users can update their information and also monetize their posts with given options
So, this is my plan:
a SPA stored in S3
a microservice for the Main app that handles authorization, this will be stored in lambda
a microservice for posts, this will be stored in lambda
a microservice for monetization, this will be stored in lambda
I am planning to use serverless so I am a little bit confused.
Where should be the AWS API gateway in the SPA or Main app? or how can I configure it
Should I use only one database and each microservice connect to it?
Should I use different databases? if so, can I how can I synchronize them
If a user logs in to the Main app, it generates a token with sanctum or passport, then this token is sent in the header request to the posts or monetization microservice, is ok this approach?
Should I install a Sanctum or passport?
Should I install Sanctum or passport in all the microservices or only in the Main app?
What can I do? thank you.

If I understand correctly you have one UI communicating with multiple microservices in the backend.
Since you are using serverless, a microservice is probably a set of functions around one functionality that are deployed together. That is totally fine.
In general you will want to have a separate storage area for each microservice. If they are physically different databases or not does not make the big difference in cloud environments because you can always change it according to your needs. The important point is that the storage area is encapsulated by the services. This might mean each microservice has an area within a database that noone else has access to.
This also means you have to use interfaces to get data of other microserivces. There are basically two ways to do so:
synchronously API use of other microservice to retrieve data.
asynchronous data replication via a message bus (event-driven architecture).
For token-based auth: your Main app will create an encrypted JWT token using a private key including user information like email, etc. This token has to be stored in the client and sent to other microservices via a header with every request. They can use decryption mechanisms to ensure the validity of the token and need the public key of the Main app for this. You might consider enter link description hereAWS Cognito libraries because they to that job for you
In general, you should overthink using microservice since they are no silver bullet. You should ask yourself the following two questions:
Do I need to scale development? (e.g. 50 developers +)
Do I need independent deployment/service evolution?
If the answer is "no" to these questions you might consider using some best practices of microservices, but I'd advice against introducing the full overhead of microservices. You could also just have some serverless functions working on a common database.

Related

Best approach for using external API for authorization with Laravel Auth scaffolding

I need to use an external API to authorize users of my Laravel app. I would like to use most of Laravel's auth scaffolding. Ideally I would not use a local database, but I'm flexible.
I'm aware of a few different approaches - using custom UserProvider, storing users locally, etc - but I'm looking to get some insight from more experienced users. Here are my thoughts:
Fetch all information from remote API, do not use local database. PROS: do not need to sync two different stores of data (API and local users table). CONS: Password Reset requires a local DB to store tokens. Security issues storing information in sessions, or speed issues if repeated API calls are needed to keep current with API data.
Initially fetch all user information from API and store in local database. PROS: Can use most of Laravel's built in scaffolding out of the box and use events to manage API. Speed and security using only local DB once authorized. CONS: data between API and local will be different and require extra work to keep them synced (I've mapped this out and it presents a bunch of issues)
Some sort of combination of both. Maybe, post-authorization I store a local token & email in the DB, and the rest comes from the API. I haven't really thought this thru.
I've spent a lot of time looking for someone who has already built API-based scaffolding for Laravel, but only found bits and pieces. I would have expected something built-in to Laravel, but maybe this is not a common use case.
Anyone have any insight?

How to Implement OAuth correctly in API with Laravel Passport?

I'm trying to create an API and use it in my own applications (web application and native mobile app) and make it available for third-party applications ( this is for future purposes).
I've read the Laravel Passport documentation, and I have some doubts that hopefully someone could help me with it.
As a developer, I always try to find the best and correct way to implement my projects and find the appropriate packages for the purposes of the projects.
Brief explanation of what I want to do:
I want to create an API and I will consume my own API in my web and mobile applications, my API has two endpoints for register and login for students and teachers. They can login with their email and password. Each user type has its own information. A teacher can have a CV, and students can see teachers' CV( the whole creating and reading CV's are handling in my API ), and they both user types can communicate with each other. I'm using laravel 6.x version to build my API. We have a section for developers in our subdomain which developers can register accounts and get/buy an access token to make requests to my API and use it, on the other hand, I want when students or teachers login to their accounts the API generates an access token for that user so then my application can use that token and pass that in every requests to make users be authenticated to access their private resources like their Dashboard as we know API's are stateless and we can't use sessions to store user credentials, so we need an access token for that.
Can Laravel Passport generate the both Developer access token, and User( teacher or student) access token?
Is it correct to use OAuth in here to develop my API?
Or can I just use tymondesigns/JWT package for these purposes?
I have to say that I'm new to Oauth and API based applications. I've read some articles about Oauth, and I'm a little bit familiar with Oauth terminology, but still, I don't know how to implement this project correctly.
So here are my questions:
What is exactly Oauth server? Is it my own server that is hosted by API?
After Laravel Passport configuration and database migration, Laravel Passport created some tables in my database, I would be really appreciated if you could tell me what is the purpose of each tables? table names are failed_jobs, oauth_access_tokens, oauth_auth_codes, oauth_clients, oauth_personal_access_clients, oauth_refresh_tokens.
I've configured my Laravel application to use the Laravel Passport and I created two Routes in my api.php file
Route::post('login','API\Auth\UserAuthController#login');
Route::post('register','API\Auth\UserAuthController#register');
and then, I created the UserAuthController.php file and wrote the login and register methods. They are working without any problem. After a user registers or login into their account, my code will generate a personal access token.
$token = $user->createToken('authentication')->accessToken;
and then students or teachers can access to the private resources of their own with this access token. Is it right to create a personal access token for my two types of users? What is exactly a personal access token?
I just know you can pass it into request header, and the server will authorize you to access private resources. what I mean by private resources is the endpoints which are protected by API middleware like this:
Route::post('/update-info','API\Auth\UserAuthController#update')->middleware('auth:api');
Am I doing right to create a personal access token when teachers and students login to their account or I should do another way to handle it?! this way works, but I'm looking for correct way if there is anything else.
The weird thing here is Laravel Passport create a token every time users login and it doesn't check if they have already created token or not? If someone can access the API endpoint, they can make a post request to /login endpoint and create a lot of tokens. Is it a problem? How to fix it?
When I create a personal access token I need to pass an argument to createToken($arg) method, and it stores in oauth_personal_access_clients table. what is the purpose of this? Is it just for Laravel Passport purpose, or maybe I need it in the future?
I have some endpoints which are not protected by auth:api middleware, for example, every user visit my application they can search for teachers name and lessons and ... , it's not necessary to make them login or register first. These endpoints are accessible to everyone in my application, and they are free to search and advance search for some information. My question is if I make it accessible to everyone, how can I protect these endpoints that only my first-party app and third-party app can access them. I mean I don't want people to access them by command line or postman or some kind of these tools without access token, I want to protect these endpoints from attackers not to make a huge requests to make my server down. How can I protect this kind of endpoints? I know I can limit requests per minute, but I don't know how much limit it? Is there any other way?
I see there is a term called clients in Oauth terminology, as I understand clients are the applications like web applications or native mobile app and any other applications that use my API are called clients. Am I right? And I think this is for third-party application authentication. I'm a little bit confused after reading Laravel Passport documentation about clients, and when I configured the Laravel Passport, it generates two clients and stored them in database. Do I need to create a client for my Applications?! How Can I ignore authorization flow just for first-party applications?
After Laravel Passport configuration, now I can see it generates some default route for clients.
/oauth/clients
/oauth/clients/{client-id}
/oauth/authorize
/oauth/token
What is the usage of these routes?! do I need them to create my first-party applications?
As I said the future purpose of this application is to make the API accessible by third-party applications, I have to create a web page that developers register an account and get/buy a token to access my API. is it possible to do it with Laravel Passport or I should write my own logic to make it work? Do I need to create a client for my third-party clients?
Thanks a lot for your help <3
It's going to take too long for me to answer each of your questions in depth, so I've
tried to link to the relevant sections in the RFC for further reading.
Essentially, I would recommend for you to use the password credentials grant flow for your first-party clients (your mobile app and web app). One of the clients that
Laravel would have created for you, would have been the "Laravel Password Grant Client" and its
documentation is available here.
You would still need to define your own "register" route, but you can use the oauth/token route
instead of your own /login route.
What is exactly Oauth server? Is it my own server that is hosted by API?
The OAuth server would be your server that is running Passport. Or in the official
terminology according to the RFC, the
OAuth server/Passport server would be called the "authorization server."
In your case, the "resource server", which your API that serves your content, would be
the same server as the "authorization server."
After Laravel Passport configuration and database migration, Laravel Passport created some tables in my database, I would be really appreciated if you could tell me what is the purpose of each tables? table names are failed_jobs, oauth_access_tokens, oauth_auth_codes, oauth_clients, oauth_personal_access_clients, oauth_refresh_tokens.
The failed_jobs table is not directly related to Passport. It's related to Laravel's queues. See Dealing With Failed Jobs.
The rest of the tables are all there so that Passport can keep track of the clients and codes it has created.
oauth_clients: See the RFC clients section.
oauth_access_tokens: See the RFC access tokens section.
oauth_auth_codes: See Authorization Code Grant.
oauth_personal_access_clients: Personal access clients don't seem to be part of the official specification, but it is basically a client for when a user wants to get an access token directly, instead of going through an app or website. Usually this would be a developer who wants to get an access token to be able to call API endpoints on their own account.
The personal access clients table stores clients that were specifically created for this purpose. Usually there would
only be one of them.
oauth_refresh_tokens: See the RFC refresh tokens section.
Is it right to create a personal access token for my two types of users? What is exactly a personal access token?
Every user would need to get their own access token, but not a personal access token.
Personal access tokens are just access tokens that were created specifically for users who wants to generate
and use the access token themselves. In Laravel Passport, specifically, they are access tokens
which are linked to the "Laravel Personal Access Client."
So in your case, your server would create "normal" access tokens for users and not "personal" access
tokens.
Am I doing right to create a personal access token when teachers and students login to their account or I should do another way to handle it?! this way works, but I'm looking for correct way if there is anything else.
See answer to question 3.
The weird thing here is Laravel Passport create a token every time users login and it doesn't check if they have already created token or not? If someone can access the API endpoint, they can make a post request to /login endpoint and create a lot of tokens. Is it a problem? How to fix it?
I don't think this is a problem. The oauth/token route is rate-limited. You can rate-limit it even more.
You can also listen to events and delete or revoke tokens
if want to limit the amount of tokens there may be for a single user.
When I create a personal access token I need to pass an argument to createToken($arg) method, and it stores in oauth_personal_access_clients table. what is the purpose of this? Is it just for Laravel Passport purpose, or maybe I need it in the future?
This table is just for Laravel Passport. It can also be of use for when you want to audit or debug something later on.
The row that you see in the oauth_personal_access_clients table, was created when you ran php artisan passport:install.
When you call createToken, a new row is inserted into oauth_access_tokens.
I have some endpoints which are not protected by auth:api middleware, for example, every user visit my application they can search for teachers name and lessons and ... , it's not necessary to make them login or register first. These endpoints are accessible to everyone in my application, and they are free to search and advance search for some information. My question is if I make it accessible to everyone, how can I protect these endpoints that only my first-party app and third-party app can access them. I mean I don't want people to access them by command line or postman or some kind of these tools without access token, I want to protect these endpoints from attackers not to make a huge requests to make my server down. How can I protect this kind of endpoints? I know I can limit requests per minute, but I don't know how much limit it? Is there any other way?
Yes, you'll have to do rate-limiting. You'll have to experiment and see what works for you.
I see there is a term called clients in Oauth terminology, as I understand clients are the applications like web applications or native mobile app and any other applications that use my API are called clients. Am I right? And I think this is for third-party application authentication. I'm a little bit confused after reading Laravel Passport documentation about clients, and when I configured the Laravel Passport, it generates two clients and stored them in database. Do I need to create a client for my Applications?! How Can I ignore authorization flow just for first-party applications?
Yes, clients are like web applications, mobile apps, etc. Usually you would have a new
client for every mobile app, web app, CLI, etc., but in addition to those apps, Laravel defines
the "Password Grant Client" and the "Personal Access Client" clients for you which have
specific purposes.
You can use the Laravel Password Grant Client for
both of your applications since they're first-party applications.
You can ignore the authorization flow for first-party applications by using the
/oauth/token route that is provided for
password grant clients.
The RFC section about the password credentials flow is available here.
You can read more about how the RFC defines clients here.
What is the usage of these routes? do I need them to create my first-party applications?
Needed for first-party applications:
/oauth/token
Not needed for first-party applications:
/oauth/clients: this is for a third-party developer to see which clients they have created.
/oauth/clients/{client-id}: for a third-party developer to update one of their clients.
/oauth/authorize: this route will be called by a third-party developer to start the
authorization grant flow with their client ID and secret.
You can read more about the above routes under the "JSON API" section in Managing clients.
As I said the future purpose of this application is to make the API accessible by third-party applications, I have to create a web page that developers register an account and get/buy a token to access my API. is it possible to do it with Laravel Passport or I should write my own logic to make it work? Do I need to create a client for my third-party clients?
Laravel Passport provides Vue components that you can use so that developers will be able to create clients. You can either use these components or you can create your own frontend and call
the JSON API routes from your own frontend.
Keep in mind that OAuth was designed originally for when third-party apps needs to access things on behalf of a user. So instead of getting access tokens, third-party apps will get a client ID and client secret and they will need to go through one of the authorization grant flows for each user that they want to act on behalf of.
If you're never going to have third-party apps that need to act on behalf of users, it might be worth considering other protocols like mentioned in the comments.

Configure a completely separated front and back end web app with Laravel and VueJS

I'm planning on creating a multi-page web app using Laravel as a back-end REST API and a Vue.js front-end to consume this API.
To be clear up front, I'm not interested in code snippets of exactly how to set this up, unless some will help visualize the architecture.
What I would like to know is how this 'Split-Stack' can be deployed in a completely separated manner. I.E. neither stack shares a codebase, and are stored in completely independent repositories.
I'm not very familiar with JavaScript frameworks beyond jQuery, so I think my lack of understanding lies mainly in the Vue.js department. Some questions which stand out in particular are:
Can a Vue.js application be hosted by a web server to serve static HTML files, if so, which one is compatible?
Can both the front and back end services run on the same server, on different ports for example, and what would be any best practices for this?
And how is login authentication affected by running a web app in this way, and should I be looking into creating some kind of OAuth authentication between the front and back ends?
After reading many blog posts, it is obvious that this architecture is possible, but I'm struggling to find details on how exactly this is configured to be completely separate.
The tools and technologies don't necessarily matter here, but any specifics for Vue.js and Laravel are appreciated.
I have a VueJS Front-End set up with an ExpressJS Back-End, which is very similar to what you are talking about. And yes, it is entirely possible. So let's take a look at each of your questions individually.
Can a Vue.js application be hosted by a web server to serve static HTML files, if so, which one is compatible?
Yes, when you run VueJS, you can either build it as a static application or serve it as a NodeJS Application.
See the Deployment section of the Vue CLI 3 documentation here. It explains how the /dist directory is used to serve the VueJS Application in the manner you are intending to.
Can both the front and back end services run on the same server, on different ports for example, and what would be any best practices for this?
I recently posted an example of how to host both your Front-End and API on the same server here. (Includes Coding Examples and Explanation). This answer references ExpressJS as the API, but the principles are the same. Really, just have your Front-End listening on port 80 and have your API operating on a different, unused port (ie: 8081).
And how is login authentication affected by running a web app in this way, and should I be looking into creating some kind of OAuth authentication between the front and back ends?
I handle all authentication on the back end. Basically, in the Vue Router, you can set a secure parameter. Then declare a router.beforeEach((to,from,next) => {}); call towards the end. This call should then check to see if the user has a valid login token and redirect them to the applications login page after setting a cookie with the URL the user was asked to login from so that they can be sent back to it after logging in.
In our case, we have the user redirected to the VueJS Route /saml/login. The /saml/login component. This component makes a call to the API and returns the address the user should be redirected to to login. In our case, it is the API (which is running on the same server, but a different port [see answer above]), www.example.com:8081/api/v1/saml_login. This then works with the IDP and receives the token and user data. This is also where you would perform you ACS functions (provisioning the user, updating the login time or user data, etc.) After receiving the token, it is placed into a cookie or other placeholder so that it can be used to validate against the token stored in the Database when the user was validated initially. (It is a best practice to set expiration's on your tokens). The user is then redirected to the url stored in the cookie that lets us know where they were asked to sign in from so they can view their content without having to look for it again. (Happy to share code on this if you want)
I think using Firebase or Auth0 Authentication is one of the best ways to do this. Firebase or Auth0 will take care of all the authentication for you and allow your backend to verify the authenticity of your front end. So that makes it much easer to separate the two.
There is an admin SDK for connecting Laravel to Firebase and there are templates and existing authentication SDK's for Vue. There are a few articles which sort of describe it but I haven't seen anything that pieces it all together yet. I was able to figure it out from 2 or 3 different articles and it ended up being easier than I thought it would be.

Laravel 5.1 Session and Socket.IO + Redis - Sending Notifications to Logged In (Known) Users and Group Of Users

I am working on a project where I want to implement real-time notifications for a specific group of users (with role of Admin) and after some research, I understood that I'll need the session in order to know which users are logged in (by default they are anonymous).
Also, I'll need to implement notifications to specific users only. (only one user, example: John Doe)
So, my questions are:
How can I transfer the session/cookie over to the NodeJS side through Redis and then emit the notification?
What should I do exactly?
Any encryption / decryption?
Anyone ever had any chance to implement anything like this?
There's almost no info about this on the internet and most of the tutorials are way too basic for my use case.
I am using Laravel 5.1 Broadcasting features to publish some notifications and display them in real-time with Socket.io (version 1.3.7). I also use Redis (version 3), NodeJS (version 5) and Express (version 4.13).
Thanks for reading!
I've been implementing (slowly) something similar for a web app using Autobahn and WAMP, it's associated protocol and router. I currently have about five different services (some written in PHP, some in NodeJS) plus the clients all communicating in real time.
The nice thing about WAMP is that it encapsulates both remote procedure calls (RPC) and publish/subscribe (PubSub) models for communication.
My authentication scheme is a bit of a kludge: on each page of the Laravel web app, there is a token value which is unique to the user and generated upon log in to the Laravel app. The Javascript uses this token value to authenticate when the client connects to the WAMP router - if it's an invalid (or stale) token, the connection is refused.
As for limiting notifications to specific users or groups, one simple way to do it would be to wrap the appropriate JS code in a function that is only called (or is only output to the client in the blade template) if the user has the appropriate permissions.
Finally, my application is strictly for use inside our firewall, so I haven't investigated using encryption/decryption.

Sync Mobile App and Web App without third party services

Currently building a hybrid app. using Ionic Framework with PHP for backend services
I am having a case where a user has got his profile in Web app and Mobile App as well.
If the user adds two stories as favourites (Its kind of a reading app) from his mobile app or Web app,how do I sync that?
Here are the scenarios:
1) User marks the stories favourites from web app and when I come online through mobile app, display it.
2) User marks the stories favourites from mobile app when he is offline(Now this will be stored in LocalDB). So again when he comes online sync with the server?
I know there are services like Firebase which provides syncing service.
But What If I would want to develop a Custom Syncing service on my own for my application? Is that an extremely complicated process?
If yes and it can be developed ,then how should I proceed ? A basic idea? What are the best practices that I should consider?
Any links would be appreciated?
I know some of the comments recommended CouchDB in combination with PouchDB. That is a much better solution than trying to implement your own synchronization service with MySQL.
However, since you're using Ionic Framework you can also use Couchbase. Take the following example application:
https://github.com/couchbaselabs/TodoLite-Ionic
If you chose this solution you would have three moving parts. You would be replacing MySQL with Couchbase Server and running the Couchbase Sync Gateway to orchestrate any data between the device and the server. You can still keep your PHP backend if you have a web version of your application as there is a PHP SDK for Couchbase.
Two write-ups on this can be found here:
http://blog.couchbase.com/using-couchbase-in-your-ionic-framework-application-part-1
http://blog.couchbase.com/using-couchbase-in-your-ionic-framework-application-part-2
In the long term, you're going to find NoSQL much more pleasant to work with when it comes to APIs and mobile than MySQL.
Can be useful to write a POST method on the backend that receives the data from your local from the app and some user data (session, access tokens and other thing you considered neceasary). On the body for the request you include the data needed to be synced. The backend takes the body. Parse it and rreturn a result (http code) Based on that you can decide if the app should delete the local data or only mark it as synced on the local database

Categories