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?
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 the buildSession method:
SessionManager::buildSession
protected function buildSession($handler)
{
if ($this->app['config']['session.encrypt']) {
return new EncryptedStore(
$this->app['config']['session.cookie'], $handler, $this->app['encrypter']
);
} else {
return new Store($this->app['config']['session.cookie'], $handler);
}
}
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
'cookie' => 'laravel_session', # ~~ ln 121 at time of writing
Ok, but that doesn't help a lot, changing this, changes it everywhere, as noted by the comment proceeding it in the config.
The name specified here will get used every time a new session cookie
is created by the framework for every driver.
And even if we could pass it some dynamic value, something like:
'cookie' => 'laravel_session' . user()->id,
This creates a paradoxical, time ending, universe imploding outcome because you are requesting the id from the user which is accessed via the session looked up by the cookie name laravel_session.. (mindblown)
Let's leave SessionManager and it's session.php configuration alone. We can see from above that regardless of how we approach this, all our session info will be fall under that single laravel_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()
$id = $this->session->get($this->getName());
So here, Laravel is fetching the session values that match the result of getName() - awesome - all we need to do is mod getName() to return a value, let's take a took at that method:
Guard::getName()
public function getName()
{
return 'login_'.md5(get_class($this));
}
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.
"Geez, that seems like a lot of work"
"It sure is Billy, it sure is"
https://www.youtube.com/watch?v=dTxQ9yhGnAg
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 core Guard with custom getName methods.
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.
Multi userlogin with same browser like google add account. for that you need follow some steps and re-write auth library which provided by the Laravel,
Steps
Tack backup of your Auth file.
Change all session store functionality to store it first in array and then store that array to session
Now you need to create the new session variable which will store the current user instance id like user 0 1 2 ...
Now you need to change all the function from you will get the values from the session you need to check if the session object is empty then user is logout else you need to get data of the user base on the user instance.
You need to change your instance when user want to switch from one account to another.
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 and Mr 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:
fall deep into this rabbit hole: "How do you do both Dr Jekyll and Mr 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)
make a decision on your own: "How do you do Dr Jekyll!" and pray you made the right choice (randomly pick user's identity and bring your users some fun with unpredictable responses)
be sly and shift this responsibility back to him: "Pardon me? Who are you? Name yourself!" (require single identity per request)
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'.
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.
Different seesions coexist between concurrent logged in users cannot just only implemented by session cookie,because cookie is stored by browser. So the logged
in user's seesion must be stored by Server.
As all we know, Once session_start is called,SessionID is created and then temp file is created in server's temporary
directory.
Diffent user has different SessionID and after session_destory called then all SessionIDs stored in Server and Cookies are recovered. You can rewrite this behavior by implementing SessionHandlerInterface. Of cause many web framework support this,Laravel has not exception.
Here is the document:
custom-session-drivers
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.
<?php
if(isset($_GET['id']) && !empty($_GET['id']))
session_name($_GET['id']);
session_start();
if(isset($_GET['user'])) {
$_SESSION['user'] = $_GET['user'];
}
if(!empty($_SESSION['user']))
echo "Hello ".$_SESSION['user'];
Currently I am doing a project which runs both on Zend Framework (For Web site) and phone gap (For Mobile). I need to use the same code for website and web service for mobile.
Now I am facing the below mentioned issue,
The web service which I am calling from phone gap is to create the session and the session was created successfully. Now i am calling the another web service to get the user details based on session id. But the details are not displaying, because the session id is giving empty. So can you please suggest how can i proceed with this?
Thanks in advance
Session is not shareable. Try saving session id to database (or file) and than read it from server side.
Can you please give more information about how sessions are managed?
From the look of it, you might need to to use both $_SESSION and potentially an implementation of the SessionClassHandler interface to store sessions in a central database.
Also you might have issues with cookies, so you might need to pass the session id via URL. But this is very insecure so if this is the case, make sure that you at least use https or put oher mecanisms in place.
I hope this helps
I am working on a site that has a login API. So when people login on my site, they will automatically be logged in to other sites.
Is their way by which a session can be setup so that other websites can use it? If not, is their any other solution?
One way - you can store your session values in database, and can use in other sites. :)
Example:-
let suppose if my site is deployed on multiple servers and end user might be redirected to different servers accordingly to traffic, then it would be good to save the session values in db.
Yes. It's possible using in example Redis for the session storage. You should look for configuring php sessions to use custom storage. Here is php man for this http://php.net/session.customhandler
What you want to do is probably using a cookie that is spread over your whole domain. This cookie can then be linked to a session. I'm currently working on something like this on Symfony2.
As example:
login.mydomain.com
application.mydomain.com
etc.mydomain.com
login.* will obviously contain my login logic + forms etc. This will also contain an API which the other applications can verify the cookie to. My Application will first check if the user is logged in. If not, it will check if it has the required cookie. If it does not, it will redirect to the login.* login page.
If it does have the cookie, it will validate this in my login.* API. Expired > redirect to the login page, if not it will return the required info of that user and "login" to my application.
The only problem I have at the moment is storing the session. I use mcrypt to encrypt the contents and store it in mysql (cookie_id, cookie_contents). I have but 1 problem, it doesn't automatically purge the expired sessions, I still have to find a solution for this.
What you are basically looking for is Single Sign-On (just a guess, but I think accurate).
i just installed wordpress (the latest) and im trying to study wordpress to make my creations secure like wordpress does or to its level.
I noticed upon logging into wordpress, it created 3 cookies.
what I'm trying to figure out is - after logging into wordpress and after it created the cookies for the user. the hash values that are inserted into the cookie, how does that value authenticate who the user is? i matched the values stored in the cookie against the values stored in the databases table called wp_users and it doesn't match..
what i usually do when authenticating a user is upon registration is i'll have a column in a table say tbl_users called hash and the value that would go in this column would be a sha1 conversion of the user name (the user created upon registration). and upon logging in on a login page and after authenticating the user by checking if he exists in the db and so forth. I would create a cookie for that user. in the cookie i would insert the hash that existed in the db and store it in the cookie. that is how i tracked the user through the pages. anyone know how wordpress is doing it? or maybe im doing it the wrong way? i don't know..
thanks in advance.
If the user authentication hash is in a cookie then it could be read, and since it already matches what is in the database directly it could be used by anyone who knows how to look at the cookies. Wordpress applies a little bit of post-processing to the user hash, I think it's in wp_settings.php.
I think it combines the user hash with the unique key you write into one of the variables in wp_config.php. After that you have a unique key built up from something publicly available like the username hash or whatever it is and from something only available in the script ie. not publicly available. It's that combination which then matches what is in the db and authenticates the user.
Hope that makes sense. Some other people may be able to give you better advice about PHP security so you may want to make your question more general.
I would look at MD5 encryption and just try to validate in your wordPress db using that. I haven't tried it but I want to do the same thing.
Just a note to you. When I was faced with the same issue while creating web apps I avoided dealing with that and just decided to use wordpress as a wrapper for my apps. You can have the login direct to your chosen template which can be a PHP page so once inside you can do anything you like but your application will be protected by Wordpress and they update their security as things change. So far for me this has been a win win win arrangement.
I validate my users using wordPress itself. You can call functions that exist in Wordpress to verify who is logged in and using your app. You can then take advantages of everything wordpress has to offer. I love having PHPMyAdmin right inside the wordPress Admin panel. This has made my life incredibly easy recently and I don't have to worry about what I don't know about security. If your developing without a security expert this might be a great option for you. Let me know if you want to know more about how I'm setting it up.
Say I have an ASP.NET webpage and I also have a PHP Blog/BBS/Website. I want all logins to be done via the ASP.NET webpage. The ASP.NET Session State is stored in SQL. Is there any way I can read/decode the Session State from PHP to tell if a user is logged on if I have the Session State cookie?
I don't think there's a supported way. You could reverse-engineer the store, but the database format may change with next .NET service pack and youe a'd be screwed then.
The only safe way would be to implement your own session state provider so you could guarantee that the database format doesn't change.
If all you need is to verify that the user is authenticated, it would be probably easier to send the user an encrypted cookie with the username and decrypt it in the PHP app.
I have never tried this but if you provided a simple web service that is part of your asp.net application but only accessable from your PHP site. You should now be able to read anything that is in session via the web serivce.
this is looks tricky, but try reading here. the issue here is know the way in what asp encodes and save the session, if you can read that format, this may help.
another way I'm thinking is to create a request to some "login" page form asp to php, where you send the login credentials and the php file creates the session, but this could be not secure if you leave it open, and also could be slow, since another request is necessary.
on the other hand I saw few sites, where once you are logged in, for example in the main site and you want to go to the forums, you click on some link that submit a form to the php login page (credentials are "harcoded" for that user in that session) and the php page login you like the "regular" behavior.
hope to be clear
Unless you specifically need full access to the entire asp.net session state, you may be better off just storing the particular pieces of information that you know both apps need to share in a shared database or file directly.
That way you can ignore most of the complexities of an asp.net session and just pick and choose the specific pieces data your apps need share with each other.