What's the best way to use HTTP Authentication in an Ajax Application that's not 100% AJAX
Asked Answered
I

5

11

I have a standard HTML login page, which I would much rather use than the standard HTTP authentication pop-up provided by browsers. Today, I am using session cookies to keep track of the session after logging in, but I'd like to be stateless and pass the HTTP authentication every time. The web services I am hitting already support this, so this is a browser-only issue.

Adding authentication credentials is trivial in jQuery, but I don't know how to keep them around. If you go from the login page (a jsp) to the Home page (another jsp) you clearly don't keep the username and password fields from the login page. I know some browsers will store your HTTP authentication credentials if you enter them from the pop-up, but I don't know if they get stored when using an XHRRequest. If they do, is there much consistency among browsers?

Also, the user needs to be able to "sign out" of the application, too. If the browser stores the authentication credentials, is there a way to clear them using JavaScript.

I feel like I can't be the first person to try to solve this. Is there some jQuery plugin or something that already handles this? Or is it simply not possible to do what I'm trying to do?

Isabelisabelita answered 3/2, 2012 at 18:40 Comment(0)
I
1

Update

The answer below was posted in 2012 and the links are mostly dead. However, since then, a more elegant standards-based approach to the same solution appeared using JSON Web Tokens. Here is a good blog post explaining how to use them.


Most answers miss the point, which is to avoid having any server-side session. I don't want any application state in the server. I'll award the bounty to answer that came closest, but the real credit goes to the rest-discuss group and Jon Moore for the correct answer and to Mike Amundsen for helping me to actually understand it.

The best answer I've gotten is to use a cookie, but not the typical automatic session id cookie given to you by most application servers. The cookie (which will automatically be sent with each subsequent request) is a user identifier and time signed by the server. You can include an expiration time with the cookie so it simulates the typical 30 minute session on a server (which means you have to push it forward with subsequent requests) as well as keeps the same cookie from being valid forever.

The XHR/AJAX part is a red herring. This will work whether you are doing XHR requests or an old-fashioned page-by-page web application. The main points are:

  • The cookie is automatically sent on subsequent requests so there's no special scripting required - it's just how browsers work already.
  • The server does not need to store any session for the user, so the user can hit any server in a cluster and not have to re-authenticate.
Isabelisabelita answered 14/2, 2012 at 16:54 Comment(2)
links do not work anymore...any chance of getting some more in depth detail?Duramen
I've updated my answer. Things have changed a lot since it was first posted.Isabelisabelita
S
4

You have 2 options:

1) Client-side storage of credentials -- not a good idea. For obvious reasons you don't want to store the username/password on the client. If you had a hashed version of the password, it might not be so bad, but still not recommended. In any case, if you're going to store on the client side, you either have to use a cookie, or HTML5 local storage (which is not widely supported, yet)

2) Server-side storage of credentials -- typically done with sessions. Then the resultant Session ID can be passed back to the client and persisted in either a cookie or in the URL of each subsequent AJAX call (?SESSID=xyz for example)

The server-side approach would be the most secure, reliable, and easiest to implement

Showdown answered 7/2, 2012 at 21:1 Comment(6)
Is it true that HTML5 local storage is not widely supported? All major browsers that I know of have versions that support it. Do you mean that those versions of those browsers to not have a large share of users yet?Isabelisabelita
In any case, I know how to create a session on the server. I'm trying to avoid having a session on the server and have my server be truly stateless.Isabelisabelita
By not widely supported, I mean you can't rely on support in the wild. True, most (if not all) modern browsers support it, but in the wild, your users will not necessarily be using an up-to-date browser. If you have a controlled target audience for which you can require compliant browsers, then local storage could be your answer.Showdown
One more question: if the browser prompts me for a username and password, it stores those somewhere (at least in memory). Does adding the credentials to an XHRRequest store those credentials in the same place? If so, that solves my problem except for removing them when signing out.Isabelisabelita
I am not sure, but it seems logical to me that it would work the same for XHR requests. These may be helpful to you: hc.apache.org/httpcomponents-client-ga/tutorial/html/… and opensourcesmall.biz/2008/06/technical-note-http-auth-with-ajaxShowdown
The best answer I've gotten so far (from other channels) is to use a cookie, but rather than have the cookie resolve a session which contains the authenticated user, the cookie resolves to authenticated user itself - i.e. It's a user id (or equivalent) encrypted and signed by the server. Subsequent requests have the cookie but it doesn't matter which server it goes to because there is no session associated with any server.Isabelisabelita
B
4

Okay, I'll take a stab at helping ...

Firstly, understand how HTTP authentication works. There are two versions - Basic and Digest. Basic transmits in plaintext, digest is encrypted. With these types of authentication, the username/password are passed in the HTTP header with every single request. The browser captures these at login and they are stored in an inaccessible browser session cookie which is deleted when the browser session is closed. So, in answer to one of your questions, you can't access these from javascript.

You could create your own session cookie variables for username and password. The jQuery functions for this are really simple. See jquery-cookie module as one example of how to set session cookies. These could be retrieved from the session cookie and sent with each ajax request and validated in the server. However, this is not a particulary good way to do authentication since sniffing the network will allow anybody to easily grab your auth details. But, it would work.

Using session cookie based authentication where the session ID is sent sent with each request is the best way to do this. At the server side, you need to have a function called for every HTTP request. This function should do the following:

   check to see if the session has been authenticated
   if no:
       redirect to login screen
   if yes:
       do authorization and allow the user access to the page

Most web frameworks support session cookie authentication and the management of session ids at the server. This is definately the way to go.

Boz answered 14/2, 2012 at 10:36 Comment(0)
E
2

This is interesting one.

Manage user sessions on server by use of cookies. Create a session when user first accesses the login page and pass the session id/key as value to one of the cookie via response. When the user is authenticated put user "key" info in cookie and "values" in application context at server. Once user is logged, any subsequent request will be authenticated based on session cookie value at server. Authorization will be done based on user "key" passed as cookie value.

On logout clear the session based cookies from server and refresh the site to default page.

Cookies are bizarre with different browsers - just a note ;)

Hope this helps.

Extensity answered 7/2, 2012 at 20:29 Comment(5)
I'm trying to avoid having any server session at all. The only way I can think to do that with a web application is to send authentication with every request and store the authentication info in the browser state, not the server state. However, I don't know the best way to store the authentication in the browser state.Isabelisabelita
storing authentication on browser leads to security hole. HTML5 does support database but are they hack-able? HTML5 is not there in older versions of browsers and your customer might not always have the latest versions too. IE will always be "Fun" to work with :-)Extensity
That's not the only place to store state. There is whatever cache the browser stores your HTTP Basic Authentication credentials in. There are cookies, as long as the cookie has all the information needed to authenticate. (I mean really authenticate, not match an already authenticated server session.)Isabelisabelita
Running authentication each request is going to become pretty intensive to scale?Rivulet
Not as intensive as having to have an in-memory session for every user.Isabelisabelita
I
1

Update

The answer below was posted in 2012 and the links are mostly dead. However, since then, a more elegant standards-based approach to the same solution appeared using JSON Web Tokens. Here is a good blog post explaining how to use them.


Most answers miss the point, which is to avoid having any server-side session. I don't want any application state in the server. I'll award the bounty to answer that came closest, but the real credit goes to the rest-discuss group and Jon Moore for the correct answer and to Mike Amundsen for helping me to actually understand it.

The best answer I've gotten is to use a cookie, but not the typical automatic session id cookie given to you by most application servers. The cookie (which will automatically be sent with each subsequent request) is a user identifier and time signed by the server. You can include an expiration time with the cookie so it simulates the typical 30 minute session on a server (which means you have to push it forward with subsequent requests) as well as keeps the same cookie from being valid forever.

The XHR/AJAX part is a red herring. This will work whether you are doing XHR requests or an old-fashioned page-by-page web application. The main points are:

  • The cookie is automatically sent on subsequent requests so there's no special scripting required - it's just how browsers work already.
  • The server does not need to store any session for the user, so the user can hit any server in a cluster and not have to re-authenticate.
Isabelisabelita answered 14/2, 2012 at 16:54 Comment(2)
links do not work anymore...any chance of getting some more in depth detail?Duramen
I've updated my answer. Things have changed a lot since it was first posted.Isabelisabelita
V
0

Slightly interesting in that you consider pushing some of the authent to the client. If you want a conventional solution, KOGI's server-side suggestion is the way to go.

But you also seem to be asking questions about memory leaks involving your user supplied secrets. Good questions. But to take a general stab at answering that I'd say it would have to be browser specific. It's browser internals, javascript engine internals -dependent where a client side application (i.e., the browser, or js in the browser) is storing the values the user inputs.

Most likely those values are not replicated needlessly throughout memory, but there's no way to guarantee that. Apart from responsible javascript coding practices, there's nothing you can do to guarantee the limit of locations of user inputs.

Slight digression

The basic point is if you store it on the client it is not really secure -- unless, the serve stores encrypted information on the client with a key that only the server (or the user via their correct credentials), has. So you could conceivably code a JS application to do some authent on the client -- much the same as how bank card (used to?) do POS authent by checking the PIN to the PIN on the card, and not back at the DB. It's based on the (somewhat flimsy) assumption the user has no direct read/write access of the "dark area" cookie/local storage on client / mag strip on bank card. So I would only advise this as disqualifier for false authents and not as a sole qualifier for the credentials.

Main point

If you do want to be stateless, just store user credentials in localstorage, or as a cookie but encrypt them with a server key. When you need them send an XHR with the encrypted / use stored credentials to the server over HTTPS, let your server decrypt them and send them to the callback. Then pass those cleartext of HTTPS to do your authent.

Vendee answered 14/2, 2012 at 15:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.