single sign on (sso) laravel

10,878

Solution 1

I implemented an SSO solution without using SAML. I'll share my solution here, hope it helps.

Single Sign On

One application runs as the main authentication server at auth.domain. Other applications run in different domains app1.domain, app2.domain, ...

Every user is linked with SSO tokens. These tokens have very short expiration times. All authentication processes (signing in, resetting passwords, registering, ...) happen only in auth.domain application.

When a user visits any applications, for example, app-1.domain:

  1. Redirect user to auth.domain/login.
  2. If the user logged in our system before, continue at step 6.
  3. Show the sign in form, waiting for valid input.
  4. Generate a new SSO token with the expiration time less than 3 minutes.
  5. Attach the auth.domain remember me cookie to the response.
  6. Return a redirection response to the app-1.domain/sso/{sso_token}.
  7. app-1.domain application read the database. If the SSO token is valid and does not expire, find the user associated to that token.
  8. app-1.domain authenticates the user found in the previous step with Auth::login($user) method.
  9. app-1.domain clear the received SSO token from the database.

After this step, the user is authenticated to app-1.domain.

Session sharing

All shared session variables should be saved to databases. I implemented a new session driver:

  • Keep the list of shared session variable names
  • When reading/writing to sessions, check the name of the session variable. If that name is the previous list, read/write the value from the database. Otherwise, use the private session of each own application.

Solution 2

If your both applications share the same databases then you can follow the approach :

-> In your database , create a default session id that will be marked as false initially

-> Now as soon as user login to any of the site, generate a new hash and replace it with the default value.


optionally

-> You can also save the hash on browser local storage with hash as a key and null as value.


-> Now when user is logging into/switching to any of the site, check that hash -> If the hash matches the default, show the login page else show the profile page.


My answer is valid only if you are using common database for login else you need mapping for this.


Alternatively you can use cookies to store hash and can access them in cross domain. Can find example at Cross-Domain Cookies By @ludovic

Share:
10,878

Related videos on Youtube

Moauya Meghari
Author by

Moauya Meghari

Updated on June 16, 2022

Comments

  • Moauya Meghari
    Moauya Meghari almost 2 years

    I have three different laravel websites, I want to make user sign in at one website then he will be automatically logged in to the other two websites. eg. if you logged in at your stackoverflow then open stackexchange you will be logged in with StackOverflow account. I have tried many packages but they end with infinite exceptions or they simply not working. Most of the packages based on SAML, I have no idea why it did not work with me? I do not know what I miss? Is there any config for this to work? I am using laravel 5.6. All the apps are on the same server.

    I have tried many solutions based on SAML, OpenID and share session, but all of them did not work with me. I do not know if I miss something. this is the last example I tried and it did not work

    this is my code

    SITE A

    $site_b = 'http://s_sesstion_2.test/';
    Route::get('/', function (Request $request) use ($site_b) {
        $session_id = Session::getId();
        try {
            $http = new Client();
            $response = $http->post($site_b . 'api/sessions/server', [
                'form_params' => [
                    'session_id' => $session_id,
                ],
                'headers' => [
                    'Accept' => 'application/json',
                ]
            ]);
        } catch (Exception $e) {
            dd($e->getMessage());
        }
        return view('welcome');
    });
    

    SITE B (route/api.php)

        Route::post('/sessions/server', function (Request $request) {
        Storage::disk('local')->put('file.txt', $request->get('session_id'));
    });
    

    SITE B (route/web.php)

        Route::get('/', function () {
        $session_id = Storage::disk('local')->get('file.txt');
        Session::setId($session_id);
        Session::start();
        //return Session::getId();// will return the same session id
        return \auth()->user();//this should return the auth user but it did not!!
    });
    

    All I want is to sign in at site A then open site B I will be signed in. I will accept any solution achieve that purpose

    • apokryfos
      apokryfos almost 6 years
      We can't know why things didn't work if you don't share what you've tried and by that I mean the actual code you've tried.