I'm in the process of building a single sign-on system and I am using cURL to send a request off to a file on the main site and return the results / their user data; however, if the user logs into the secondary site via a cookie (ie; they aren't currently logged into the main site) I need to make sure they get logged into the main site at the same time and set some session variables so that they don't continuously have to keep logging in via a cookie on the secondary site.
Obviously we normally would end up with a different session id on the file I am calling via cURL and hence setting any $_SESSION variables there wouldn't be available to the secondary site; so I tried passing the session_id from the secondary site with the call via cURL and then in that file I did this to set the session id so that any $_SESSION variables I set there would then be available to the secondary site.
// Get session ID
$sid = trim($_GET['session_id']);
// Set the session id so we can get the added session data below via the forum
session_id($sid);
session_start();
However when I do that and try and access the secondary site the page won't load, it just hangs - I tried removing that code and loading it again but it won't load until I restart Apache.
Btw.. if it matters, this is on my local dev machine, which is Windows XP Pro.
Any ideas!?
I’m assuming here that both your main and your secondary site are on the same server and use the same session settings, especially the same session.save_path, is that correct?
If so, that’s where your problem lies:
The default session handling mechanism of PHP works using files to save the session data.
And to avoid concurrent write access to the session file, the file gets locked as long as one script (one script instance would be more exact) is still working with the session. Every other script that wants to access that particular session has to “wait”, until the first one is finished using the session.
So with you trying on your secondary site to start your session with the session id already in use on your main site, the script on your secondary site can’t access the session because of that locking.
And since your main site’s cURL request is waiting for the secondary script to finish, which is itself still waiting for access to the session … you’ve got yourself a nice deadlock here :-)
What you can do, is call session_write_close in your main site script before making your cURL request – at that point all data is written to the session file, and the file lock is released.
You have to be aware though, that you can not use the session again in your main site script instance after that – well, you can still read data from and push data into the $_SESSION array, but since the session is already closed, all data that you alter in that array after that point will not be persisted any more. So do what you have to do with the session in your main script, then close the session – and then make your cURL request.
Edit: Well, come to think about it – not sure if the above actually helps here … because your whole approach might be flawed already. Calling a script via cURL on your secondary site will not actually set a session cookie for your secondary domain in the user’s browser – because every response of that secondary site’s script does not “land” in the browser, it lands in your main site script, because that’s where you doing the request from.
I think what you really need here, is to call a script from your secondary site in the user’s browser (JavaScript/AJAX request, iframe, embedded image), so that it’ll set a cookie with the session name and session id as value under your secondary site’s domain – only that will make PHP able to “recognize” the user’s browser once they navigate to your secondary site. Actually opening the session will not be necessary (still assuming that both sites use the same session), because the session is already started, and all it needs for PHP to pick it up on the secondary site is a matching session id from the cookie.
So try doing that instead – but be aware of the problems you might run into with that, since the browser will consider the cookie for the secondary domain as a third party cookie when you are trying to set it in the context of your main site (and the domains don’t match, e.g. one is not running on a subdomain of the other or something like that).
Related
I have an existing webapp in php and js and I am trying to add authentication to it. I have figured out the part on how to create a login page and authenticate against my organisation's LDAP server where multiple users have their accounts created.
My question is about the $_SESSION variable being same for all users who visit.
If a user visits the page and I set
$_SESSION["username"]="xyz";
$_SESSION["logged_in"]=true;
and then if another user logs in, will the $_SESSION variable be totally new for him or will the keys like "username" and "logged_in" be set with the previous user's data?
If not, then how does PHP or the httpd webserver know whether the tab is closed or a new request has come in?
If I open multiple tabs in the browser (or multiple browser windows) will it all have the same $_SESSION variable in the backend?
Basically I have questions about the lifecycle of the $_SESSION variable.
When the server receives a HTTP request, a Session ID is generated by the server and is sent back to the browser. The browser stores the Session ID in a cookie so it can re-use it. The ID forms the link between the browser and server, so that the server can identify subsequent requests as coming from the same browser.
The browser then sends that Session ID to the server (in a HTTP header) in every request the browser makes to the same server. PHP uses that ID to find the right session data for that ID in its storage. The actual session data is private and never leaves the server. Only the ID goes to the browser.
All of this means it's impossible for two users to share the same session data, because each session ID is unique. (It would technically be possible to steal another user's session ID if they were using an insecure HTTP-only connection to the server and you were able to monitor their network traffic, or even with HTTPS using a man-in-the-middle attack, but that's a whole other topic.)
If you close the browser, the session cookie is destroyed, by default. Therefore when you re-open the browser and go back to the same website, it will send a request without a session ID and will be given a new session ID by the server.
The other thing that would cause a new session to occur is if the session times out on the server. The server will have a session timeout value. It records what time a session was started and when the last request was made using that session ID. If no requests occur using a given session ID for timeout minutes after the last one, then the session ID will be destroyed and the browser will be given a new session ID next time a request occurs, regardless of whether it sent the previous one or not. This is usually why you find you're logged out of a website if you don't use it for a few minutes.
I'm new to PHP, I read other articles without finding the answer I'm looking for, but still don't know if what I want to do makes sense or not.
I'm using PHP 7.
My user authentication page, checks credentials and then executes session_start(), creating the session server-side and a cookie client-side in the browser.
Each other page of the web application then calls session_start() to resume session information, in this case checking the cookie. Everything works fine so far... at least when I have a single login.
I'd like to be able to have more than one user SIMULTANEOUSLY logged in the same browser (on another tab for example.) using cookie. I don't want to append the session ID to the URL.
I managed to create different session on the server-side using session_id() before session_start() in the authentication page based on username, but the problem is on the client side.
The first successful login (session_start()) creates a cookie and the second login updates the same cookie corrupting the previously created session.
Therefore when it comes to resume the session, session_start() will resume only the last session, mixing the data fetched from DB based on session info.
Is there a way to make session_start() create a cookie for each login and make PHP resume the correct session using cookies?
Any ideas?
FURTHER DETAILS:
I'm updating a legacy app trying to fix some security issue. The need for multiple sessions comes from administrative purposeses where admins access the same site. The reason why it's needed a separation of session is that depending of the session info, the data are fetched from a different database. Therefore, a regular usage would only need one session per user, but the administrator he needs to make multiple logins viewing different data depending on that login.
The default PHP behaviour is to handle sessions using cookies.
..and the default behaviour for browsers is to "reuse" the same set of cookies if you revisit an URL in another tab.. So, like mentioned below:
The simple way probably is to start another browser. Not the same browser but like firefox and chrome, if you have multiple browsers installed.
Another way would be to install a browser plugin, like Sessionbox for Chrome or Multifox for Firefox.
Edit, for clarity: I can think of two cases when multiple sessions would be used:
During development. Depends on the application, but an obvious case would be testing communication between two users.
After deployment. Though I've never seen a site that required multiple logins for the same user account.
This is my frame of reference. Based on this I assumed the question was for development. I'm not suggesting that the site should require installing extra packages. Flash would be about the only one that's ever gotten away with that..
You can use the same session but change the variable names that you are looking for:
if ( $_SERVER['REQUEST_URI'] == '/admin/' ):
$session_name = 'session1';
else:
$session_name = 'session2';
endif;
session_start( $session_name );
I have ServiceSite.com (SS) and multiple GameSite.com's. All games authenticate through SS and then log in with their own personal databases. That's all done with a simple JSON API, no need to log into SS to get into a game.
I have the one goal of logging into a game and accessing the features of SS through the game, such as accessing a player's Contact List and Profile, both of which are shared between all games. While in GameSite.com/play, they'll hit a link to ServiceSite.com/contacts and get the response as if they were opening it from ServiceSite.com. I use JSON Web Tokens to manually log the user into SS, to simulate a real login to ServiceSite.com.
This works... so long as they're on the same domain. Meaning, as I'm developing a game, I'll use ServiceSite.com/tempgameurl and any call to ServiceSite.com has no problem establishing and keeping a session. But once the game gets its own domain, or if I'm working on my localhost, I cannot get it to recognize the session on subsequent requests. If I want a response, I will always have to pass the JWT token, which is not suitable for what I'm doing. The goal is to load a game, "poke" SS to create a log in, and then if a player were to visit ServiceSite.com, they would have the session as if they'd logged into ServiceSite.com's front page with their login manually.
In short, I expect that once I hit my first JWT request and make a session on ServiceSite.com from a GameSite.com, that's it, the session is made. But it seems to only actually make a session if I'm requesting from the same domain. I do see it create a session properly, filling in $_SESSION, but that data simply does not persist if the request originates from a non-ServiceSite.com URL.
Sessions and Cookies are domain dependent, it is a browser security issue. You cannot cheat this. However, there is a "trick" you can try, even though it is a bit more complex:
You need to set a cookie for each domain:
authenticate the user, emit a JWT code and create a key=>value type of record in a shared storage (database most likely). The key should be unique, the value should be JWT code and also set an expire time of 20-30 seconds.
in the response HTML you need to make the browser set cookies for the other domains. That can only be done on those domains. So you need to fool it with something like:
<img src="http://anotherDomain/setCookie.php?key=keyFromSharedStorage" style="display:none;" />
in the setCookie.php, check the shared storage and retrieve the JWT based on the $_GET['key']. Then set a cookie with that JWT.
You could pass the JWT directly, but passing a key that expires fast should be more secure. Add an image for every domain.
Instead of a cookie you can create a session on each domain. Same principle really.
Well try saving your needed data and sessions in database itself. It seems to be small amounts of data and logs.
After a game save the sessions on the database and open from whichever place you are at.
What are sessions and cookies in php and where are they stored?
I searched but I can't find the exact answer.
HTTP is stateless. This means whenever you request something from a webserver, it will serve the requested page and forget you immediately.
Imagine a shopping cart:
You add something to the cart. The server will have some sort of data storage to remember that you put item X into the cart, but since HTTP is stateless, the next time you call the server, it won't remember it was you who put something into the cart. The webserver could create a form on the returned page and populate this with each and every item you added. Now you add another item, but also send, which item you already had added. Repeat. This is effectively transfering the entire state of your interaction on each and every request. But that's rather inefficient and insecure.
With Sessions enabled, the webserver will create a unique id, the so called Session ID for you. This will be used to link you and the cart on subsequent requests. Usually, the Session ID is sent to the browser in a Cookie. Technically, this happens through HTTP Headers:
Set-Cookie: PHP_SESS=abcdefg123456
The browser reads the headers and creates or updates the cookie file in the cookie storage inside the browser. Usually cookie files are nothing more but key/value stores in text files on your computer. If you want to have a look at them google for "where does [browsername] store my cookies".
On the next request to the same webserver, your browser will send the cookie along and the webserver is now able to associate this ID with some data store (whatever is set as the session save handler) on the server, for instance login information, the contents of a shopping cart, etc
See the reference to the PHP Manual I've linked below your question for further details.
Cookies are stored in the browser, not in PHP. You can get the cookies the browser sent by looking in $_COOKIE['cookiename'], but as far as i know you can't set cookies like that -- you need to use setCookie(), or possibly header('Set-cookie: ...').
The sessions can be stored anywhere, but they're most often just files on your server's filesystem; your php.ini (or the ini_get() function) would probably be helpful in finding out where. Try:
$session_file_name = ini_get('session.save_path')."/sess_".session_id();
A cookie is some piece of data the server requests the client to store and send in consequent requests.
A session is some data stored on the server, and connected to the user via a session id. This session id is most of the time stored in a cookie.
A session can be stored on the filesystem, most likely in a temp directory, but also in a database.
Both cookies and sessions have a expiration date connected to them, so they wont last forever.
Cookie is a small piece of data stored on the client-side(browser) and session is a text file stored on the server-side, whose name is stored in the cookie.
That's all.
I am interested in knowing how session management and cookies work in PHP. I want to know their underlying mechanism, like how the browser interacts with the cookies, and how the cookies are used to validate the session data in the server.
Is there any web resources that allow me to learn that?
In PHP in particular, the standard way sessions work is that PHP generates a random session ID, and puts it in a cookie. (By default called PHPSESSID) This cookie is handled by the browser by saving it locally on the user's machine, and is sent with every request to the domain it belongs to.
This session ID is then used to refer to a data store on the server machine, by standard located in /tmp/ on an apache install on linux. This is where everything in the $_SESSION array is stored between requests.
As you may notice, this is only as safe as the cookie is, as there is no real authentication between the user and server that the user is the "real" owner of the session ID. This means that so-called "session hijacking" is possible by sniffing the cookie and inserting the cookie with the session ID on the attacker's machine. This can be used to take over an account on a webpage, and browse around it just as if you were the original user, because to the server you are.
There's also an alternate, even more unsafe, way of keeping the session alive that PHP supports. This is done by sending the session ID as a GET variable with every link. As you may notice, this means that if a user simply copy-pastes one of these links, he will be giving away all his credentials. =)
Further information could be found in the PHP manual.
From PHP’s Session Handling manual:
A visitor accessing your web site is assigned a unique id, the so-called session id. This is either stored in a cookie on the user side or is propagated in the URL.
This unique id is a big random number that is stored on the server side to match it next time the client makes a new request. It typically goes into the /tmp directory.
A cookie is a bit of data that's associated with a HTTP address.
I.e.
1/ Browser requests www.google.com
2/ www.google.com response includes setting a cookie
3/ From this point on and as long as the cookie is valid (there's an expiry time associated with it), each subsequent request made by the browser to www.google.com/anything includes the cookie above
For details: http://en.wikipedia.org/wiki/HTTP_cookie
A cookie permits creating a session in the otherwise stateless HTTP protocol in the sense that it allows a client-server conversation to be isolated from other clients interacting with the server.