15

I'm building a multi-domain/multi-store ecommerce application in Laravel and would like to keep the user logged in when he or she changes from store to store.

But for as far as I know Laravel's Auth service saves the logged in user in the session and the sessions can't be accessed by other domains.

Is there a way (maybe a package) to achieve this, without leaving my application prone to possible security problems?

Thanks in advance!

Luuk Van Dongen
  • 2,391
  • 6
  • 26
  • 40

7 Answers7

8
  1. Capture the session id Session::getId() in Domain A
  2. send the captured session id via HTTP POST to Domain B
  3. Access the sent session id in domain B $sessionid_from_domainA = $_POST['session_from_A']
  4. Set session in domain B Session::setId($sessionid_from_domainA)
  5. Start Session in domain B Session::start()
Sharath TS
  • 96
  • 1
  • 3
  • I wish it was possible but its not. If its the same laravel installation but with different domains, Once you login to your app from Domain A, you cant send a POST request to itself and start a session. – Omer Farooq May 10 '16 at 13:22
  • I found an easier way to do this, check my answer – mateos Nov 07 '16 at 05:53
5

If you want to share the session between multiple subdomains in that case you have to set the domain name config/session.php has set the domain name.

Example: if you have new.example.com and test.example.com so you have to set the domain name as example.com

'domain'     => env('SESSION_DOMAIN_URL','.example.com')

Solutions there worked for me, specifically setting the domain and then clearing my browser cookies & cache.

Muhammad Raheel
  • 19,823
  • 7
  • 67
  • 103
Chirag Prajapati
  • 529
  • 6
  • 10
  • Better still just create a .env variable like (SESSION_DOMAIN=.example.com). Works for me with on same laravel project. – DAVID AJAYI Apr 17 '20 at 16:36
  • Can cookie be issued to specific subdomains only? Such as new.example.com and test.example.com only? and not for other subdomains? To access the session from another Laravel project, do I have to implement the User model again? Should I change my driver to Cookie instead of file? – Luke Galea Oct 30 '20 at 14:27
  • I have a little problem with this approach. I use multiple dynamic dns domains. i.e domain1.freemyip.com, domain2.freemyip.com etc – SaidbakR Jan 31 '22 at 22:08
4
  1. On domain A create an image like so <img src="https://DOMAINB.com/setcookie?id={{ Session::getId() }}" style="display:none;" />

  2. On Domain B create a Route like so:

.

Route::get('setcookie', function(){
  Session::setId($_GET['id']);
  Session::start();
  return 'Cookie created';
});`
  1. Done, Now you should be able to get your user by $user = Auth::User;
mateos
  • 1,405
  • 1
  • 17
  • 26
  • For anyone using this, I'm not certain to whether this method is secure, it was how google used to do it, however now they use OAuth – mateos Oct 19 '17 at 06:13
  • 1
    For simple things that can be stored in a session, this is life saver – bksi Sep 02 '18 at 22:36
  • I used this method, the only small change I made was to pass the encrypted session id, instead of the plain id. Like this: `Session::setId(Crypt::decrypt($_GET['id']));` Also, I ran into an issue on IE9 and below. They require the P3P header to be set in order to have the cookie be set correctly for the other domain. So I added this line below the Session::start(): `header('P3P: CP="This is not a policy"');` You can read more about P3P headers in [this post](https://stackoverflow.com/a/17727566/847937). – Harry Potts Apr 24 '19 at 12:19
  • @HarryPotts Does session need to be stored in database for this to work? – mujaffars Nov 25 '21 at 07:08
2

I know this is not exactly what was asked for, but, for development and testing purposes, I did this:

In config/session.php, try changing this line

'path' => '/',

Into this

'path' => '/;SameSite=None; secure',

allowed me to authenticate from different domains.

Now, you should be able to write a simple middleware to prevent unwanted hosts. Something like this.

namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Closure;

class TrustedHosts{
    public function handle($request, Closure $next){
        //$host = $request->getHost();
        $host = $request->headers->get('origin');
        $enviroment = env('APP_ENV');

        if ( $enviroment == 'development' ) {
            $trustedHosts = array('localhost', 'dev.mydomain.com');
        }
        else {
            $trustedHosts = array('anotherdomain.com', 'mydomain.com');
        }
        
        $isHostTrusted = in_array($host, $trustedHosts);
        
        if ( !$isHostTrusted ) return response("I'm a teapot", 418); //Or any other code and message that you prefer.
        return $next($request);
    }
}

And group it in the middleware group that includes the session stuff.

sergio0983
  • 1,232
  • 8
  • 15
1

I am working on something like that too a single sign-on system, still working to find a solution, but here is a start http://laravel.io/forum/03-14-2014-multiple-domains-how-to-share-login

On laravel you can change the /app/config/session.php driver to cookie


Edit:

This is what I have done.

You can share cookie accross domains using pixel images. For example when you login on domain1.com you want to create a cookie on domain2.com, right after login on domain1.com you need to have something like this

<img src="http://www.domain2.com/create-cookie?param=hash">

on domain2.com the route above:

  1. will check first if a user is logged in
    1. if its not logged in will read the hash (for example email address), check if there is a user with that email, and login it there, also set a cookie
CatZ
  • 43
  • 10
  • 2
    WARNING: Do not send the email over in plain text, This means I could edit the html tag and basically log into any account on the other domain. Encrypt the text using your App Key. – mateos Nov 07 '16 at 05:41
1

You can manually set which domain the session cookies will be registered, and thus have them persist across different sites. Just edit config/session.php, in the following section:

<?php
/*
    |--------------------------------------------------------------------------
    | Session Cookie Domain
    |--------------------------------------------------------------------------
    |
    | Here you may change the domain of the cookie used to identify a session
    | in your application. This will determine which domains the cookie is
    | available to in your application. A sensible default has been set.
    |
    */

    'domain' => null,
?>

You're still restricted to a single top-level domain, though. So you can have store1.shops.com and store2.shops.com sharing sessions, but not myshop.com and shopsmart.com.

If you need something in this format, you'll probably fare better by creating an authentication service, and using access tokens to validate the credentials. You might also give a look at services like OneLogin.

DfKimera
  • 2,076
  • 2
  • 21
  • 39
0

Based on this answer of Chirag Prajapati. Yo could use $_SERVER['HTTP_HOST'] in the env entry:

From /config/session.php

'domain' => env('SESSION_DOMAIN', $_SERVER['HTTP_HOST']),

Then from the app root: php artisan config:clear and don't keep attention to warning messages, just be sure at the end you have gotten Configuration cache cleared! By this way your app session will work fine on whatever domain you have.

SaidbakR
  • 13,303
  • 20
  • 101
  • 195