Logins and Redirects: What is the best HTTP flow for a webapp login? - http

This question is a question about login flows for web-apps in general. I'm most interested in answers that optimize for usability and performance while maintaining security.
What is the most appropriate way to handle unauthenticated requests to bookmarked URLs?
To demonstrate the problem, here are some routes and respective behaviors for an example application:
GET /login -> Display the authentication form
POST /processLogin -> process the username and password,
if unauthentic...re-render the login form;
otherwise...display the default page
GET /secret -> if authenticated...display the secret resource;
otherwise...display a login form
POST /secret -> if authenticated...perform a desirable, but potentially
non-idempotent action on the secret
resource
otherwise...display a login form
Option 1: Display login screen, redirect to desired page
User clicks bookmark
GET /secret -> 200, surreptitiously display login form with hidden field path="/secret"
POST /processLogin -> 302 to /secret (value of path parameter)
GET /secret -> 200, secret resource displayed
Analysis: Hopefully, your client is a modern browser, non-compliant with HTTP, such that it performs a GET after a 302'd POST. This applies across the board. Should I be worried?
Option 2: Redirect to login screen, redirect to desired page
User clicks bookmark
GET /secret -> 302 to /login
GET /login via redirect -> 200, login form displayed with hidden field path="/secret"
POST /processLogin -> 302 to /secret
GET /secret -> 200, secret resource displayed
Analysis: Same problems as above. Added problem that the URL displayed by the browser during login changes, which is confusing to the user and breaks bookmarking, link sharing, etc.
Option 3: Display login screen, display desired page
User clicks bookmark
GET /secret -> 200, surreptitiously display login form with action="/secret"
POST /secret -> 200, secret resource displayed
Analysis: Sadly, the refresh button is now also broken: refresh will cause the user agent to re-POST with a warning, instead of re-GETing /secret. They user gets a warning, but if they ignore it, something bad happens.
On the bright side, you minimize roundtrips with this technique.
Option 4: Redirect to login screen, display desired page
User clicks bookmark
GET /secret -> 302 to /processLogin
GET /processLogin via redirect -> 200, login form displayed with action="/secret"
POST /secret -> 302 to /secret
GET /secret -> 200, secret resource displayed
Analysis: Same problems as options 2+4.
Option 5: ???
Is there another technique I'm missing?
In general, which of these techniques would you recommend?
See Also
What is correct HTTP status code when redirecting to a login page?
What kind of HTTP redirect for logins?
HTTP response with redirect, but without roundtrip?

Option 1 & 3 are not following the HTTP RFC as "surreptitiously display login form" contradicts 200 GET response, where "an entity corresponding to the requested resource is sent in the response" is expected.
Option 2 is OK. All modern browsers support 302 on POST and many REST-based frameworks (like RoR) actively use it. Alternatively in "302 to /login" you can already create the session (cookie) and store the URL in session, to avoid passing the original URL in GET parameters. From usability standpoint, you can have an appropriate message on login page too (I think the URL mismatch is irrelevant here - you can't let the user see the content anyway).
Option 4: when you POST to /secret, HTTP RFC expects you to "accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line", but all you are doing is logging in and not creating anything new under /secret.
So following HTTP RFC, your best choice is Option 2. Actually Option 2 is also in line with POST->Redirect->GET design pattern, which helps to address the issue of unpredictability in bookmarking URLs to POST'ed resources.

My $.02: I recently implemented using option 2 (although I stored /secret in a session, not in the login form as a hidden field).
I don't entirely share your concerns:
Added problem that the URL displayed
by the browser during login changes, which is confusing to the user
and breaks bookmarking, link sharing, etc.
Redirecting to /login, and the subsequent change of URL, tells the user that before they can continue there's something else that needs to be done first: logging in.
Since a login page will look entirely different from the 'target page', I don't see how that will confuse people into bookmarking and/or link sharing the login page instead of the target page (since the login page won't contain the information they want to bookmark/share anyway).
And if you're worried about 302's breaking the standard (although every single browser I know will happily break it), consider using 303's instead.

Note that mickeyreiss is correct, using AJAX Option 3 works without the drawback of the broken back button. However, it means the user has to have JavaScript enabled. This being said, if you program your form properly, you can detect whether JS is present, if not use Option 1.
Note that the 302 response is fine, however, you may have problems with caches. You have to make sure that nothing gets cached if you want to show 2 completely different pages/forms on for the same URI. (/secret showing the login and then the actual secret.)

I almost always use option #2, simply because the content returned by a URL is consistent. While today's secrets are hidden behind a login, tomorrow you may want to open it up or display mixed public/secret depending on authentication at the same URL. In that case, option #2 will be most like what Google would expect. Any content bait and switch is looked down on by Google and in the extreme case, all of your pages would have duplicate page content (ie. login form).

I would choose the option using AJAX:
login page and hide the content
the user enters the login and the password.
Authentication is done in the server side.
The server returns a result
if successful use location.href to set the page you would like to
go to, or else you can output a message saying the login is not
valid.
In your server you will be testing on a _SESSION variable, if not set redirect to the login page..

Related

Push into browser's history via HTTP headers

I need to make the client to navigate through a series of redirects. After the user arrives to the destination, I'd like to allow the user to go back to an intermediate page to be redirected elsewhere.
For example, take the following diagram:
Current Page -> Processing Page -> Landing Page
Status: 3XX
|
V
Alternative Page
Disclaimer: I do not have control over Landing Page but I do have control over the others.
From the Current Page, the user is sent to the Processing Page which, after checking the DB, redirects the user to the Landing Page. What I would like is, if the user presses the back button, to be sent back to the Processing Page so it can redirect the user to the Alternative Page.
The problem is that, because of the 3XX status code, the Processing Page is never injected into the browser's history so when the users goes back, they are sent to the Current Page directly.
So far, I've achieved my goal by making Processing Page to return 200 and force a redirect via JS as the first thing but it feels like a clunky solution.
Would it be possible to achieve the same outcome with a combination of HTTP headers? Another solution, since I have control over Current Page is to place the decision making algorithm there but this is a complex enough page already that I'd rather prefer to avoid this option.
Many thanks!

Direct linking to a gov.uk ASP page (possibly user session related)

I am unfamiliar with ASP but I need to link directly to a page on the http://carfueldata.direct.gov.uk/ website which I assume from the .aspx extension is built in it. My problem is that when a user first clicks on the link, the destination page immediately redirects them to the home page, presumably because there is some kind of user session required (?), I do not know. Not a good user experience for my visitors. The second time you follow the link it displays happily. The chances of my users following a link twice is slim.
Is there a standard URL parameter or something that I can append to tell the ASP platform to generate a user session and not redirect.
To see problem for yourself open this link in a new window, then close it, and repeat. First time it will redirect to home page. Second time does not: http://carfueldata.direct.gov.uk/search-new-or-used-cars.aspx?vid=30392
It looks like they are using session for this purpose. As far as I know there isn't any way to override this.
But you can do some work around for this.
Call jQuery ajax function to homepage and redirect on its complete event.
While calling the ajax function the cookie (ie session set) will be set on client's browser and after the ajax call redirect user to the page.( The page that won't allow users to visit directly)
Click to go
function LinkClick()
{
$.ajax({
type: "get",
url: "http://carfueldata.direct.gov.uk",
dataType: 'jsonp',
complete: function (msg) {
window.location.href=" http://carfueldata.direct.gov.uk/search-new-or-used-cars.aspx?vid=30392";
}
});
return false;
}
When you initially submit the request to the website, you receive a 302 status (moved (temporarily)) and a redirect to the home page. This is because there is no session ID cookie in your request. The redirect response from the server creates the session ID cookie for you and from then on, the site honours subsequent requests.
I don't know which client library you are using, but it should be possible to intercept the redirect request sent by the server, and replace the redirect URL to the homepage with your original request URL. Since the redirect response contains the session ID cookie, we can assume that the session has been created and your original request should work immediately without the redundant visit to the home page.

Whats the difference between the following page transfer methods

What is the difference between the following:
Server.transfer?
Response.Redirect?
Postbackurl?
When should I decide to use which?
Server.Transfer tells ASP.NET to redirect processing to another page within the same application. This happens completely server side. This is more "efficient" as it happens on the server side but there are some limitations with this method. The link below describes some of these.
Response.Redirect actually sends a HTTP 302 status code back to client in the response with a different location. The client is then responsible for following the new location. There is another round trip happening here.
PostBackUrl is not a "transfer method" but rather an property that tells the browser which URL to post the form to. By default the form will post back to itself on the server.
Here's a good link: http://haacked.com/archive/2004/10/06/responseredirectverseservertransfer.aspx
Server.Transer() works server-side. It will reply to the client with a different page than the client requested. If the client refreshes (F5), he will refresh the original page.
Response.Redirect() replies to the client that it should go to a different page. This requires an additional roundtrip, but the client will know about the redirect, so F5 will request the destination page.
PostbackUrl is a property telling an ASP control where to go when clicked on the client. This does not require an additional round trip while keeping the client informed. If you can use this method, it's generally preferable to the other choices.
Server.Transfer:
Transfers request from one page to other on server.
e.g. Browser request for /page1.aspx
Request comes on page1 where you do Server.Transfer("/page2.aspx") so request transfers to page2 And page2 returns in response but browser's address bar remains showing URL of /page1.aspx
Response.Redirect
This statements tells browser to request for next page. In this case browser's address bar also changes and shows new page URL
PostBackUrl
You can mention it on Buttons or Link buttons. This will submit the form to the page provided. It is similar to the:
<form method="post" action="/page2.aspx">

How to know if the current Servlet request is the result of a redirect?

Is there a way to know if the request has been redirected or forwarded in the doGet method of a Servlet?
In my application, when a user (whose session has timed out) clicks on a file download link, they're shown the login page, which is good. When they login, they are immediately sent the file they requested, without updating the page they see, which is bad. Basically, they get stuck on the login screen (a refresh is required).
What I want to do is interrupt this and simply redirect to the page with the link, when a file is requested as a result of a redirect.
Perhaps there are better ways to solve this?
The redirect happens client-side. The browser is instructed by the previous request to send a new request, so to the server it does not make a difference. The Referer header might contain some useful information, but it's not certain.
When redirecting you can append some parameter, like ?targetPage=dowloadpage and then check if the parameter exists. You may have to put this in a hidden field on the login page if you want it to be transferred through multiple pages.
If you're using container managed authentication, then I don't believe you can detect this since the server will only involve your resource once authentication has been completed successfully.
If you're managing authentication differently, please explain.

Drupal : customize status messages (of contact form)

I am setting up a website using drupal 6 and trying to be minimalistic. I use contact form, and it works pretty well. Once the message is sent, it is redirected to the front page of my site with a message "Your message has been sent.".(with a div messages status). How can one change it like,
customize the message content
instead of redirecting to the home page, display a node (another page)
thanks for any suggestion.
For more advanced forms and customisation like you mention above, you should try webform. Webform has the ability to redirect a successful submission to another URL and have a custom status message as well.
Change the string for the message. To do that, you can either turn on the locale.module or get string overrides module.
You can create a small custom module to redirect the user using the #redirect property of the Forms API. See here for an example (and check the comments for potential issues).
Alternatively, consider using one of these modules:
Node Destination
Custom (Form) Destination
Rules
Page manager redirect

Resources