Can someone properly guide me regarding using an already existing login system in Laravel for other subdomains containing different Laravel projects/apps? Some of the options I saw are the following:
laravel uses session to store user related data and one of many use-cases of that data is to check whether the user is authenticated or not.
Now, if you want to have the user logged in in the subdomain as well, then you need to share the session and cookies between both projects.
You need to ensure that your env file has the following setup
domain.com > .env
APP_URL=http://domain.com
SESSION_DOMAIN=.domain.com // important
sub.domain.com > .env
APP_URL=http://sub.domain.com
Now the data will be shared. But one more barrier would be encryption. Your subdomain will not be able to read any cookies because it would be encrypted. Solution to this is to use same APP_KEY in both projects or disable encryption for targetted cookies in both projects by adding the name of cookies in app/Http/Middleware/EncryptCookies.php.
protected $except = [
'test'
];
You will have to create a session_table in database so that all domains can access it (assuming all projects are connected to one database)
php artisan session:table
Then you will have to clear your cookies before seeing this in action by running command
php artisan config:cache
Resources
Checkout the following link to understanding this better
Hi @gitwithravish amazing thank you! I really appreciate your help and effort. A few questions:
My projects will not connect to the same database - the aim of having different projects is to load different applications. In app.domain.com I have a users_table, and a devices_table where users can view which devices they own. In dashboard.domain.com I want to store other incoming data for a particular device type (which would additionally have a different dashboard then other devices) and authenticate said users who own a particular device type as approved by app.domain.com. How should I proceed in this case?
My logic is simple i.e. If a user logs in from dashboard.domain.com (or app.domain.com), I want a session to be created and then a user can use dashboard.domain.com as well.
How do sessions work exactly? i.e. if I store a session for a user_id in app.domain.com, what information would be available at dashboard.domain.com? Should I recreate the exact same model at dashboard.domain.com ?
I'd recommend having one shared database accross all your applications which would have your users stored in it. If that is your app application then share that database with the others by setting up extra connections in your database.php config file.
Then you can follow the steps @gitwithravish talked though and have all applications talk to the shared database which has your user information.
Thank you for this. It crossed my mind but I wasn't exactly aware that with one Laravel project I can connect to multiple databases.
So as a recap:
My 'app' Laravel project is a project where users can sign up and see devices which they have bought
If I have another Laravel project, say 'Device Dashboard' I should get that project to connect to two different databases (the app database and another database where appropriate tables and incoming data from the device would be stored) and use the same auth methods based on the users table in 'app' ?
I think that the method which @gitwithravish talked about was using cookies - where the user session would be stored in a cookie across different subdomains. I understand the 'cookie' concept - however I am not sure as regards the implementation. i.e. from the 'Device Dashboard' when I fetch the cookie and session, what data about the user will I get? And should I implement the same exact model in 'Device Dashboard' ?
@lukegalea16 It sounds like you want single sign-on. You would have one application that acts as your authentication server. Install Passport here, and then create clients for each of the other applications. Those other applications can then send users to your single sign-on server to authenticate, and will be returned back to the original application. You can then use that information to look up or create a user in that applicationâs database, and log them in.
Hi @martinbean, yes exactly my 'app' should act as an authentication server. If I create a user in 'app' - do I have to create that user again in my 'other application' in order to be able to login that user in my 'other application'?
Do you have any reference for passport being used as sso ? A tutorial to follow perhaps.
@lukegalea16 Youâd use Passport to allow the other applications to authenticate using OAuth. Your applications would then get an OAuth token (and user ID) when the user authenticates. Youâd then need to use that user ID to either look up or create a user in your applicationâs database so you have a primary key to use in foreign keys.
Youâll probably want to. create a custom Socialite provider for the applications to be able to authenticate against your SSO server.
I've never used Passport before so I'm new to it. Should I use OAuth with it?
From what I understood, when a user logs in - an OAuth token is created at my 'app' and then my applications use that to reference in their databases.
Some thoughts about this:
Where is the OAuth token stored at the user's end?
Is the OAuth token stored in the database of the other applications?
For each request made on the other applications, do I use OAuth token in 'app' to check if the user is still logged in?
I am sure if I am overthinking this and maybe passport handles most of this stuff.
"Youâll probably want to. create a custom Socialite provider for the applications to be able to authenticate against your SSO server."
@lukegalea16 Passport is OAuth. Itâs a wrapper around an OAuth server. Adding Passport to your project adds an OAuth server to your project to allow you to issue OAuth tokens for your users.
You wouldnât really store the OAuth token. When the user is redirected back to the initiating app, youâll get a user ID. Use that ID to look up the user in the applicationâs database, or create a new one if you need to.
No. See above.
Again, no. Once youâve got a corresponding user in the database of the application trying to authenticate, you can authenticate the user and use session-based authentication like normal:
public function handleProviderCallback()
{
/** @var \Laravel\Socialite\Two\User $user */
$user = Socialite::driver('your_sso_app')->user();
// Look up user by ID in SSO app, or create new one if you need to
$user = User::updateOrCreate(
['sso_server_id' => $user->getId()],
['name' => $user->getName(), 'email' => $user->getEmail()]
);
Auth::login($user);
return redirect()->intended('/');
}
So your application will have a users table with a sso_server_id column. You can drop the password column as the userâs password will be stored on your SSO server; not in each applicationâs specific users table.
As a recap, my other applications login system should have the following steps:
1. Authenticate against 'app' server to check entered user credentials
2. If the user credentials are correct, login the user using Auth::login($user);
My questions or concerns are now the following:
Is Passport needed to authenticate the credentials on the 'app' server? i.e. can't I do an API call with the credentials towards 'app' server to check if the credentials are correct? Said API would return a true/false for example.
When a session is created using Auth::login, what data will the session have? Will it have the $user data stored for example?
As for the $user passed to the Auth::login, I do not plan on replicating the users table on my other applications again - although I will be using the sso_server_id in my other applications tables to create linking with devices etc. When you are using the updateOrCreate method, are you duplicating the user in your other applications? Can I create a temporary $user variable instead? Which would be held in the session data and used to get the sso_server_id throughout other pages of the application.
Hi @martinbean , I am currently testing this out and tried skipping the updateOrCreate method. Is it possible to modify the Auth::login such that a user can have a session created even if it does not exist in the DB ? Thanks