What application component in a LAMP stack, sets the "Set-Cookie" header - php

The application I'm working with accepts three different types of login. Automatically if the client connects from certain IP-adresses, or a POST request, either from a normal browser rendered form, or towards a JSON reading API-endpoint.
All three options boil down to calling the same functions for registering the user as logged in, and generating a session.
Despite the code paths being the same as far as I can determine, two of these consistently work, while one consistently fails to add a 'Set-Cookie' header to the response, even though the application logic generates a sessionid that gets sent in the reponse body.
Never having needed to dig into how session authentication works to this level of detail, I realise I don't understand. where the 'Set-Cookie' header, should come from. Should application logic always build the header manually? Will PHP do it automatically once session_start() is called? Does Apache do it based on other parts of the header?
I sort of ruled out 1 by failing to find anything with grep -ri "set.cookie" * in the codebase I'm working with.

session_start sends a session cache limiter and a session cookie (or sets a $_GET key with your PHPSESSID).
This function is where the Set-Cookie paramater is sent from. Apache will then pass it back to the browser when it sends the page back.
You need to remember however that storing the cookie is actually up to the browser. By and large they will be set without issue, but certain conditions will stop this from happening, such as the security settings in Internet Explorer or the user rejecting cookies entirely.
Further reading:
http://www.php.net/manual/en/function.session-start.php
http://www.php.net/manual/en/function.session-get-cookie-params.php
http://www.php.net/manual/en/function.session-status.php

Related

WordPress 4.9.3, $_COOKIE, and session_start()

I solved my problem but I don't know why it works. I was hoping someone could shed some light?
I have a WordPress site. If a new user visits the site, they see a generic element on the homepage. When they visit an internal page, a cookie is created. When the user visits the homepage again, they see a customized element based on the cookie.
The problem I was having was that when the user returned to the homepage from an internal page, even though the new cookie was set with the right value, the $COOKIE superglobal was not reset until a refresh was performed. You could naviagte to as many different pages as you'd like, but still the superglobal was not reset until a literal refresh was performed. This was using both setcookie() and the setting the super global directly.
This was fixed by adding session_start() to the header. I thought session_start() affected the SESSION super global. Why did this solution also affect the COOKIE superglobal?
Why did this solution also affect the COOKIE superglobal?
Most likely it didn't, not directly - but by sending different headers regarding caching, it influenced how your browser was instructed to check for changes when displaying the same URL again, whereas before you simply got a stale copy presented from the cache.
it just seemed odd to me that cookies would be cached as well
Well not the cookie itself got "cached" - but the document in which you made any output depending on the cookie was. You still saw the first version of the page you loaded - the PHP code behind this was not executed again, because the browser did not actually request the URL from the server again.
But when the server sent a response header indicating that this page should not be cached (or that the client you check with the server before displaying the resource again) the first time it was loaded - it caused the browser to make a new request when you returned to the page.

Varnish and PHP session validation

I run a largely session-dependent site in front of which I want to put Varnish.
The user might get a Set-Cookie header on the first request, it depends on which URL he entered.
PHP's session_start is used.
How can I make sure that the Cookie header from a client is in fact related to a valid PHP session if Varnish is in front?
If there is no Cookie header sent from the client I can easily send it to the backend for a Set-Cookie.
Right now I use an AJAX request which returns a Set-Cookie header for each page, that is supposed to (in)validate the Cookie for a user, and it seems for work for 95% of the visitors. The missing 5% is causing a lot of headache.
Is there a widely used method for solving this?

Cache validation - Browsers validate cookies in cache incorrectly?

I have the following situation:
User makes request to PAGE A that displays a form (server stores cache of this page)
User submits the form to CONTROLLER that is used for form submit
CONTROLLER finds an error in user submitted data, sets a cookie ERRORS detailing such, and redirects the user back to PAGE A
PAGE A shows the original content plus the ERRORS (server stores cache of this page)
PAGE A deletes ERRORS cookie
This works, but only if I don't use cache on my system for PAGE A.
Problem is that, after deleting the cookie, browser makes a request to my server without the cookie and gets a 304 Not Modified error and, as a result, the browser still shows the page with the error, instead of without (from the original request). Server stores cache properly (for page that has an error as well as an error-free page).
Basically the server has two cached pages now: PAGE A and PAGE A WITH ERRORS.
Browser, whose last known page was PAGE A WITH ERRORS asks for server a page with conditions of PAGE A, instead of PAGE A WITH ERRORS, since cookie does not exist anymore. But it thinks that the 304 response is about the PAGE A WITH ERRORS, instead of PAGE A. I even checked the data sent by the browser, it knows that it got PAGE A WITH ERRORS with the ERRORS cookie, yet accepts 304 not modified when making requests without that cookie. It does not validate its own cache against the conditions it was created under.
Doesn't browser validate its cache with the cookies it has set?
And is there a workaround for it without setting some GET variables for each request? Another alternative is to tell servers to never cache pages that have such an ERRORS state set, but that would be a hack.
Apparently the solution was to include this as a response header:
Vary: Cookie
This will take cookies into account in caching engines.
EDIT:
There is a problem though: Chrome, Internet Explorer and Firefox work as expected, but Safari and Opera both ignore 'Vary' header when storing and validating cache.
client-side sessions (a.k.a cookies) are probably not sufficient for this scenario...
would suggest server-side sessions instead. Even if Vary headers might work - with $_SESSION you'll be on the save side.
Cache-control: public is probably not what you want. Public essentially says that you're working with static, globally accessible data. It doesn't change per user. It's caching globally because you're claiming that the data is global.
As soon as you start changing per user, caches are having their assumptions violated. 'private' is more akin to what you want.
That will mean that you get less of the good middle-man caching, however. You might be able to hit some middle ground with re-validation, or with appropriate use of Vary headers.

Proxy server for logging in

I'm writing a proxy script that ideally does the following things:
Proxy waits for request for certain protected pages from end user
Posts login information to page. The login information is hidden to the end user.
Proxy reads the 'set-cookie' response from the server and 'hands off' this cookie to the end user. At this point the end user is finished interacting with the proxy.
I've decided to take this approach because I found it very difficult to proxify certain types of pages (like those with lots of javascript code). I thought that this logical flow would be sufficient because my only requirement is to hide the login information from the end-user and my manager says that handing off the cookie is fine.
My problem is that I cannot think of how to 'hand off' the cookie to the end user. First, the cookie is generated for my proxy server, not the user. Does this matter? It seems that I get all the set-cookie responses, but when I make another request those cookies disappear.
Can anyone point me in the right direction, or point out any inconsistencies in my thinking?
Thanks!
Most likely your problem is with cookie scope - if it's not defined, the cookies you hand off back to the user from your proxy are valid only for your proxy URL and are never submitted when the user is redirected to the original site.
It is also possible that the server on the other end tracks not only the cookie presence but the source IP as well.

Do AJAX requests retain PHP Session info?

If I had a user logged onto my site, having his id stored in $_SESSION, and from his browser he clicked a 'Save' button which would make an AJAX request to the server. Will his $_SESSION and cookies be retained in this request, and can I safely rely on the id being present in the $_SESSION?
The answer is yes:
Sessions are maintained server-side. As far as the server is concerned, there is no difference between an AJAX request and a regular page request. They are both HTTP requests, and they both contain cookie information in the header in the same way.
From the client side, the same cookies will always be sent to the server whether it's a regular request or an AJAX request. The Javascript code does not need to do anything special or even to be aware of this happening, it just works the same as it does with regular requests.
If the PHP file the AJAX requests has a session_start() the session info will be retained. (baring the requests are within the same domain)
What you're really getting at is: are cookies sent to with the AJAX request? Assuming the AJAX request is to the same domain (or within the domain constraints of the cookie), the answer is yes. So AJAX requests back to the same server do retain the same session info (assuming the called scripts issue a session_start() as per any other PHP script wanting access to session information).
Well, not always. Using cookies, you are good. But the "can I safely rely on the id being present" urged me to extend the discussion with an important point (mostly for reference, as the visitor count of this page seems quite high).
PHP can be configured to maintain sessions by URL-rewriting, instead of cookies. (How it's good or bad (<-- see e.g. the topmost comment there) is a separate question, let's now stick to the current one, with just one side-note: the most prominent issue with URL-based sessions -- the blatant visibility of the naked session ID -- is not an issue with internal Ajax calls; but then, if it's turned on for Ajax, it's turned on for the rest of the site, too, so there...)
In case of URL-rewriting (cookieless) sessions, Ajax calls must take care of it themselves that their request URLs are properly crafted. (Or you can roll your own custom solution. You can even resort to maintaining sessions on the client side, in less demanding cases.) The point is the explicit care needed for session continuity, if not using cookies:
If the Ajax calls just extract URLs verbatim from the HTML (as received from PHP), that should be OK, as they are already cooked (umm, cookified).
If they need to assemble request URIs themselves, the session ID needs to be added to the URL manually. (Check here, or the page sources generated by PHP (with URL-rewriting on) to see how to do it.)
From OWASP.org:
Effectively, the web application can use both mechanisms, cookies or
URL parameters, or even switch from one to the other (automatic URL
rewriting) if certain conditions are met (for example, the existence
of web clients without cookies support or when cookies are not
accepted due to user privacy concerns).
From a Ruby-forum post:
When using php with cookies, the session ID will automatically be sent in the request headers even for Ajax XMLHttpRequests. If you
use or allow URL-based php sessions, you'll have to add the session id
to every Ajax request url.
It is very important that AJAX requests retain session. The easiest example is when you try to do an AJAX request for the admin panel, let's say. Of course that you will protect the page that you make the request to, not to accessible by others who don't have the session you get after administrator login.
Makes sense?
One thing to watch out for though, particularly if you are using a framework, is to check if the application is regenerating session ids between requests - anything that depends explicitly on the session id will run into problems, although obviously the rest of the data in the session will unaffected.
If the application is regenerating session ids like this then you can end up with a situation where an ajax request in effect invalidates / replaces the session id in the requesting page.
That's what frameworks do, e.g. if you initialize session in Front Controller or boostrap script, you won't have to care about it's initalization either for page controllers or ajax controllers. PHP frameworks are not a panacea, but they do so many useful things like this!
put your session() auth in all server side pages accepting an ajax request:
if(require_once("auth.php")) {
//run json code
}
// do nothing otherwise
that's about the only way I've ever done it.

Categories