In our web app, If I use a single browser, login to our application as user A, open another tab and login as user B - User A loses his session data. I assume this is due to a shared cookie made out with the user-agent. Is there a way to concat its name with a username? so that sessions can co-exist between concurrent logged in users using the same browser on the same machine?
We use Laravel 5. Is there any way around it?
I don't exactly know what do you need this for, but as a developer I sometimes have to log into an application with multiple users. To do that I usually use incognito mode or if its more than 2 users I had some luck using this extension in chrome.
I know its not an answer to your question but it just might be what your looking for.
The easiest is just a URL based sessionID which could be a security issue depending on how your application is designed, especially when sharing urls with non-expired sessions.
Since L5 doesn't support php native sessions anymore, you'll have to use a custom provider like below:
This will use sessionID in the url for laravel V5:
https://github.com/iMi-digital/laravel-transsid
Basically the session is URL based, so you can just login in a different tab and get a new sessionID, and that person can easily do a "open page in new tab" to have two pages of the same user if needed as well.
The library above locks the session to the IP and User Agent so link sharing won't accidentally leak a session.
tl;dr: Yagni
Consider a person (http client in your case) with 2 identities:
Dr Jekyll
andMr Hyde
.He visits his new friend Sir
RM1970
(http server in your case): "How do you do,RM1970
!".Here is the problem. Poor
RM1970
need to welcome back the monster, and there are few options:Dr Jekyll
andMr Hyde
!", which incredibly complicates further conversation (your ACl, for example, will need to operate with list of identities, and make a decision about priorities if they conflict realtime)Dr Jekyll
!" and pray you made the right choice (randomly pick user's identity and bring your users some fun with unpredictable responses)The later is how it actually works. The browser provides the latest confirmed identity.
You've been asked to change this, but do you really want it? Hold the line and don't accept this responsibility.
If you are not going with first 2 dead-end options, you will need to ask user on which behalf he sends the request. The best option here is to make your frontend stateful, maintain list of opened sessions, and provide a UI for user to pick one. It is almost the 3rd Ryan Bemrose's option, but store this data on client side, and send only the chosen one. No changes in laravel backend required.
The problem here is switching tabs will not automatically switch user, and will be rather confusing, providing very little difference with logout/login path, which is already implemented.
Some browsers support multiple profiles (example), which may be an acceptable alternative. Basically it is the same as 1st Ryan Bemrose's option, but does not require multiple browsers installed, and can benefit from permanent cookies, aka 'remember-me'.
Any major browser will only store one session cookie for a site, but the site developer gets to choose what's in that cookie. It seems like your site is storing user information in the session cookie, which is then getting overwritten when the other tab stores different information in the same cookie.
You don't provide much detail about how your specific site operates, but here are a few general ways of approaching this problem.
1) Use different browsers for different users. Different browsers don't share cookies between them. If your goal is simply to test your site with multiple users, this is the way. You can also use Incognito/Private mode to log in a separate user, as this mode doesn't share cookies either.
2) Don't use session cookies to store user information. This is a non-starter on most websites, but if this is an internal site or strictly controlled environment, you may be able to pass user identification via the URL, POST data, or some other hidden identifier in the request.
3) Store data in the session cookie for all currently logged in users. Depending on the web framework, it may be possible to create a map of
user
->cookieData
and look up the correct one based on which user is making the request. This is an advanced technique, and I don't actually know if Laravel exposes this level of control.Laravel Session Background
Sessions
Skip this section for a quick easy solution
In Laravel, session cookies are created via the
Illuminate\Session\SessionManager
class, namely through thebuildSession
method:SessionManager::buildSession
In this method we can clearly see that the name of the session comes from our
config\session.php
, looking in particular this line:session.php
Ok, but that doesn't help a lot, changing this, changes it everywhere, as noted by the comment proceeding it in the config.
And even if we could pass it some dynamic value, something like:
This creates a paradoxical, time ending, universe imploding outcome because you are requesting the
id
from theuser
which is accessed via thesession
looked up by thecookie
namelaravel_session
.. (mindblown)Let's leave
SessionManager
and it'ssession.php
configuration alone. We can see from above that regardless of how we approach this, all our session info will be fall under that singlelaravel_session
key.Guard
Maybe Guard will have some more information.
Guard is your key to auth into your app, and one of the many things that makes Laravel awesome for quickly creating applications.
The method to look at is
Guard::user()
.One of the first things
Guard::user()
does after some initial cache and logged out checking, is a session check.Guard::user()
So here, Laravel is fetching the session values that match the result of
getName()
- awesome - all we need to do is modgetName()
to return a value, let's take a took at that method:Guard::getName()
That's pretty straight forward.
$this
refers to the Guard class, so the md5 will effectively always be the same (if anyone knows the 'why' behind md5'ing the class name which would be the same each time, leave a comment).There are a few places where this should be updated, such as
getRecallerName
.So from here, you can extend the core
Guard
class and splice in your getName and getRecallerName methods.You will probably want to wrap some service provider around this, write some unit tests, possibly even overwrite the original auth manager.
See the next part
The quick "I just need an answer" answer
Ollie Read has already created a solution, found here:
https://github.com/ollieread/multiauth
I encourage you to have a look, especially the custom
Guard
class which extends coreGuard
with customgetName
methods.I don't know how complicate it is to code it into laravel but this could be one solution:
You use a different session name, has to be a string, and code it into the url every time so the application knows which user made a request. So you can call the session variables by a normal name.