14

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

rahul singh Chauhan
  • 323
  • 1
  • 4
  • 15
Moauya Meghari
  • 471
  • 2
  • 6
  • 23
  • Do this websites share database? – Kyslik Jul 26 '18 at 08:11
  • @Kyslik yes, they share the same database – Moauya Meghari Jul 26 '18 at 08:47
  • You're expected to attempt a solution and show us what you've tried. SSO is a really broad topic with many many ways to solve and we can't just speculate what would work best for your case. – apokryfos Jul 29 '18 at 07:59
  • @apokryfos I have tried many packages based on SAML and it did not work, and I have tried to share session but did not work either – Moauya Meghari Jul 29 '18 at 08:51
  • 2
    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. – apokryfos Jul 29 '18 at 09:00
  • @apokryfos I added code blocks from the last example I have tried. and the link to verfied answer – Moauya Meghari Jul 29 '18 at 09:10
  • @MoauyaMeghari - you can see https://stackoverflow.com/questions/51435654/how-to-setup-saml-to-mutiple-domain#51468770 answer from @n-b . You can setup `simplasamlphp` or other saml library 'lightsaml' etc. – Jaydp Jul 30 '18 at 06:48
  • https://stackoverflow.com/a/40458694/4075877 this solution may help. – Gunnrryy Aug 03 '18 at 13:02

2 Answers2

22

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.
Hieu Le
  • 8,288
  • 1
  • 34
  • 55
  • 1
    Nice solution! How do you handle the logout? – Philipp Nies Dec 10 '19 at 13:04
  • When users log out, I redirect them to the `auth.domain/logout` to clear the common session then redirect him/her back to the original site. – Hieu Le Dec 10 '19 at 14:25
  • Hi @HieuLe , may i know on *Step 4*, does that mean we'll encounter every 301 redirection whenever the 3 minute token has expired? or we can do it on http/ajax request to refresh the token? – Mavichow Apr 12 '20 at 14:07
  • I've been trying to use ````Auth::login($user)```` but I get ````BadMethodCallException: Method Illuminate\Auth\RequestGuard::loginUsingId does not exist```` please have a look https://stackoverflow.com/questions/66465177/laravel-6-how-to-autologin-user-in-a-different-laravel-application-without-pass – PHP User Mar 04 '21 at 14:21
1

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

Rnayak
  • 96
  • 11