What Causes A Redirect Loop? - php

Here are my pages:
Redirect Page:
if user has an open session, redirect to the proper resource
else redirect to login page
Login Page:
if user login info is valid, redirect to $_SERVER['HTTP_REFERER']
else display login page
When you visit the redirect page, it sees that you do not have a valid session and redirects to the login page. You can then login no problems, but after authentication I receive the "This webpage has a redirect loop." page in Chrome.
It's not a true loop, since there are several ways out (IE provide valid login details and go to destination resource, provide invalid login and receive error message, etc). But I can see the browser's confusion (going from a to b to a again).
Any ideas how I can solve this problem?
Cheers

$_SERVER['HTTP_REFERER'] will always be the login page since you have to load the login page right before you successfully login. So once you successfully login, the referrer is the login page, so the login page redirects you to the login page, which you still successfully logged in, so it logs you in over and over.
Rather than relying on $_SERVER['HTTP_REFERER'] you should probably store the page they are trying to get to in either a $_SESSION or $_COOKIE variable. Most likely session will be better, depending upon your setup.

After submitting your login details, $_SERVER['HTTP_REFERER'] is going to be the URL of your login page, since the last page the user saw was the form for them to login.
Consider storing the 'redirect to' url in the PHP Session before you redirect to the login page. You could also pass it as a parameter when you redirect to the login page, but I can see that approach having potential security flaws (such as redirecting users to another site, adding fake HTTP headers etc)

My guess is:
If the user has a session, but not a valid one (e.g.: the session hash does not match), it gets redirected to the login page (since he has a session). But when he gets there, you check if he has a session, and he does (but it's not valid), so you redirect him to the index resource. There, you check if the session is valid, but it's not. So you redirect him to the login page. And so on...
How to fix it? Check for session validity (not only for existence) in both the login page and the other resources.
And of course, if the HTTP_REFERER is login, ignore it and forward to the index resource.

You should always check that the $_SERVER['HTTP_REFERER'] variable contains valid data, as it is not to be trusted since user agents provides this value.
From the php.net manual
The address of the page (if any) which referred the user agent to the current page. This is set by the user agent. Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. In short, it cannot really be trusted.

You could let your login page do the redirection in one pass (without redirecting back to the "redirect page").

Related

Symfony2 - redirect user back after re-login, if logged out because session expired?

In Symfony 2.8, if user's session expires, he'll be logged out and redirected to login page after he makes new request.
After user logs in again, how can I redirect the user back to the page he wanted to open before he was redirected? Or at least to the last page he opened (page, on which session expired)?
You could let the login action check or there was a referer, and update the security target path. Make sure that referrer is safe before you do this ;-)
$yourReferer = $request->headers->get('referer');
$this->container->get('session')->set('_security.main.target_path', $yourReferer);
The login mechanism will use that target_path after a successful login attempt.
Using the header to get the referrer (ie $request->headers->get('referer')) will not work in this case because it will always return the login link.
Thanks to #Carrie Kendall - for his answer

Remembering which page the user wanted to go to

I have a few links on my page. Most of them will redirect to the homepage if the user is not logged in. Instead of doing that, I want to direct the user to the login page, then direct them to the page they originally wanted to go.
So, for example, if the user is on index.php, and clicks on page10.php without being logged in. S/he should get directed to login.php. After logging in, the website should remember that the user originally wanted to go to page10.php.
How do I do that remembering part? I understand I can use cookies and/or php sessions, but are those the most appropriate ways (in this scenario) of remembering that the user wanted to go to page10.php?
No need to use sessions or get variables, simply access the HTTP_REFERER from the $_SERVER array on your login page, set it to a hidden element in your form then after submission redirect back to that URI
Append desired URL as part of the link. So if a user is not logged in redirect him:
login.php?url=<desired_url>
read the variable on login page, and upon success direct it there instead of index.
To get the URL on the server side look at $_SERVER['REQUEST_URI']
$_SERVER manual
First, redirect to login.php?return=ORIGINAL_URL
In login.php set $_SESSION['return'] = $_GET['return'];.
After a successful login, check if there is a $_SESSION['return'], if there is, and is a valid URL, redirect to it and unset $_SESSION['return'].
That's it.
PS: The reason why you should use session is because the user may not login successfully on the first try. Or may not have an account, he may want to register first. This way he will be redirected to the appropriate page even after creating an account.
Logging a user in implies that you will be using sessions. Sessions usually use a cookie, but they can be implemented by passing a session id around in the request if you don't want to or can't use cookies.
The appropriate way to do this is to use sessions as follows:
1) The authentication check redirects to the login page
2) the login pages checks if the target page is set in the session and if it is not it sets it to the referrer
3) if the login form is valid the target page is removed from the session and the user is redirected to the original page
4) otherwise the form is redisplayed.

How can I capture the address that user was going to so I can redirect them after login?

I'm directing users to a page on my site from email (possibly an email client). When they reach the site they are presented with login screen and the address where they were headed is lost.
How can I capture the entire address that they were trying to visit, so that I can redirect them to it once they log in?
You need to capture the address as you redirect them to the login page, (ie when you check if they are logged in) I'd recommend storing it in a session. A very quick method would be to redirect to /login.php?from=store.php for example, however this is not the best way as the $_GET['from'] could be hijacked to redirect the user somewhere else, which is why I use $_SESSION to store this value.
First of all, I don't know much about Symfony so I will let you know what I do in PHP.
There are a few techniques I use depending on the app.
Option 1: I send the user to the page they are to log into, e.g. mydomain.com/landing.php and set a SESSION variable with the URL before redirecting to the login form. When the login is performed successfully there is a header function that will redirect to the originating page where the logged in user can now interact with the page.
Option 2: I create a login function and where there is no login SESSION or COOKIE the form is called, upon submitting the form using action="<? echo $_SERVER['PHP_SELF']; ?> I set a POST variable and before any HTML tag is called I have something like
if(isset($_POST['run_login'])) {
include('my_login_handler.php');
}
This takes care of the login activity and doesn't require any redirection to the target page as it is handled inline.
Option 3: Like option 2, I create a login function here there is no login SESSION or COOKIE, but this time I POST the data to my_login_handler.php rather than including it. Upon successful authentication to the site I call header('Location: '.$_SERVER['HTTP_REFERER']); that will redirect to the referring page meaning I don't need to set any special COOKIES or SESSION variables to handle to redirect back to the target page.
The right option, regardless if it is here or not, is going to depend on your application and what you can/need to do. So have a play with the various suggestions and see what works best in the application you're currently working on.
Good luck!

Redirecting user back to originally desired URL after login

Example:
User is not logged in
User has items in their shopping cart
User goes to /checkout
User is redirected to the /login page
User logs in successfully and should be redirected back to the /checkout page
How does the login action know to redirect the user to checkout in this case? I want this to work in many different situations not just /checkout.
Would a query string parameter in the login page be enough?
eg: www.example.com/Login.php?returnUrl=[someUrl]
After the authentication is successful, the user would get redirected to the url specified in the query string.
...
Edit: This is a general solution, it many not be an option given the framework you are using. But something to consider.
I posted a bit of the code from my "My_Form" class that has "referrer" tracking built in to the form on SO1249274. The other solutions posted there may help you solve your problem as well.
I've done where we redirect to /login with a simple parameter of 'comeback'. Login sees the parameter, and checks the referer to see that its one of our pages. If it is, it redirects back to that referer. Works really well. Otherwise, one can put the 'destination' of the redirect-after-login in a different parameter (wether it be a querystring or session or flashmessage)
I use session variable to keep the requested URL. When he logs in successfully i do check if this session variable is set. If it is set, i do redirection to requested URL.

PHP: Returning a user to their original page after login

Are there any 'best practices' concerning how one should return a user to their original page after logging in to your website, specifically in PHP? e.g. if I'm viewing a StackOverflow question while not logged in, how would you ensure that I return to this question if I logged in?
From my research, it seems a lot of advice centers around the $_SERVER['HTTP_REFERER'] variable. Basically, you take note of the referer and store it in the session, then redirect back to that page when you're done.
The problem with this is that HTTP_REFERER is unreliable at best.
This is set by the user agent. Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. In short, it cannot really be trusted.
— [http://php.net/manual/en/reserved.variables.server.php]
Any edits to the referer to redirect to other areas of the site will be handled by routine permissions checks. If the referer gets blanked out, it might be acceptable to simply redirect the user to the main page of the site rather than the page they came from. This seems needlessly user hostile though, and I was hoping there would be some better way to handle this.
On login page:
<form action="controller/LoginController" method="post">
<?php
if (isset($_SERVER['HTTP_REFERER'])) {
echo '<input type="hidden" name="l" value="'.htmlspecialchars($_SERVER['HTTP_REFERER']).'" />';
}
?>
<!-- the rest of the form -->
<input type="submit" />
</form>
At login controller, you take in the $_POST['l'] value and see whether or not this URL is on your own website. If it isn't, redirect to your default page, else redirect to this URL.
Make sure that on your login page if user is already logged in, you redirect the user back to home page or something. This will prevent cases like redirecting back to login.
$_SERVER['HTTP_REFERER'] is a browser responsibility. It is also most of the time rather reliable. If the browser doesn't send, or if you are worried about it, you can use session instead.
on every page simply set $_SESSION['lastvisitpage'] to the current page URL. On login then you redirect to $_SESSION['lastvisitpage'].
Since $_SERVER['HTTP_REFERER'] can be faked by a user at any time, one should always treat is any other user-supplied variable by properly escaping it.
It would be better if you store the last visited page on your own, maybe with the help of a session.
If the user requests a page from your website the first time, start a new session and initialize last-URI with the current URI. Update this last-URI whenever another page is requested until it’s the login page. Now if the authentication is successful, you can redirect to user to the URI in last-URI.
And if you have a login form on every page, use a hidden input where the current URI is stored in.
if(user_not_logged_in())
{
$link = "http://example.com/login?continue=path/to/current/page";
echo 'Loign';
}
This is how I, and sites like Google, does it. You would need to make sure that you check the continue variable and sanitize it of weird URLs first however.
Another option is use AJAX, and allow the user to login from any page. User logs in, you submit the form via AJAX, refresh when the request comes back.
I think you might be asking if the user specifically clicks on the login link on a menu, you automatically think that the user wants to be redirected to the page that they pressed the button from. This I believe is a flaw in logic. Take StackOverflow. Just because I press login doesn't mean I want to return to the question I was last on.
However, there are some instances that it would be correct to assume the person wants to go back, such as if I upvoted a question and got the popup telling me to login. If I clicked the link there, it would be safe to assume that I want to go back. But just the login link on the nav bar doesn't have that implied meaning.
I would suggest make an AJAX call to login the user and on successful AJAX response just refresh the current page.
Use PHP sessions and the $_SESSION object to define a "continue location". Here is the code I use in one of my projects. When the user is logged in, I set the $_SESSION['loggedin'] to TRUE.
Here is the code to check on a sub-page, let's call it "sub-page.php" if the user is logged in. If not, I set the $_SESSION['contloc'] to the url of the that page and redirect the user to the login page.
// We need to use sessions, so you should always start sessions using the below code.
session_start();
// If the user is not logged in redirect to the login page...
if (!isset($_SESSION['loggedin'])) {
$_SESSION['contloc'] = 'sub-page.php';
header('Location: index.php');
exit;
}
In the script where the user / password is validated, I then get the value of $_SESSION['contloc'] and redirectx the user to the page the user initially opened:
$continueLocation = '';
if(isset($_SESSION["contloc"])&& !($_SESSION["contloc"] === "")){
$continueLocation = $_SESSION["contloc"];
$_SESSION["contloc"] = ''; //reset continue location
header('Location: ' . $continueLocation);
exit;
}else{
header('Location: menu.php');
}
(if the user did not come from a sub-page, the authenticate script simply redirects to the menu.php)

Categories