Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

single sign on (sso) laravel

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

like image 703
Moauya Meghari Avatar asked Jul 26 '18 07:07

Moauya Meghari


People also ask

Does SSO mean single sign-on?

What is Single Sign-On? Single sign-on (SSO) is an authentication method that enables users to securely authenticate with multiple applications and websites by using just one set of credentials.

What are examples of a single sign-on SSO service?

Social SSOGoogle, LinkedIn, Apple, Twitter and Facebook offer popular SSO services that enable end users to log in to third-party applications with their social media authentication credentials.


2 Answers

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.
like image 149
Hieu Le Avatar answered Oct 14 '22 00:10

Hieu Le


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

like image 42
Rnayak Avatar answered Oct 13 '22 23:10

Rnayak