How to force authentication challenging for every request in REST? - java

My understanding is that a RESTful service should be totally stateless. Every time I invoke the service, I must pass all the information it needs to operate properly.
However, when it comes to authentication I get rather confused about how this should work, particularly in terms of session management.
I am using basic authentication and the first time I make a request, the client gets challenged (or I can pass the authentication information in the header from the beginning). But once the user has been authenticated, the server will not challenge this client anymore as long as the session is alive.
This means that I need to provide some mechanism for the current user to logout (terminate his/her session).
It would look like the right way of doing this would be to change my configuration somehow so that every request is challenged for authentication, but I have no clue how this plays with session management.
Am I supposed to invalidate the session manually after every request?
Or is there way to force the clients to be challenged every time a request is made?
You can find lots of questions out there about security with REST, and even books about how to implement different models of authentication. But I have not found a good answer on how to deal with session management, logging in and out. So either I am doing something wrong or I am misunderstanding something important here.
I would appreciate any thoughts or guidance on how this should be properly handled.
I am using Jersey 2.4 with Tomcat 7.

If you're authenticating with HTTP Basic, the client is challenged the first time only because the Authorization header isn't being sent from the client. Once it's sent and the server sends something other than a 401, the client caches those credentials and re-sends them with every request.
You shouldn't create sessions in a stateless app, not only because they aren't used, but because they require overhead to manage (even empty ones). The servlet architecture, however, cannot prevent code from creating sessions, such as when the code calls either httpServletRequest.getSession() or httpServletRequest.getSession(true). So you need to ensure that you don't use any code (or frameworks) that do this.
Interestingly enough, Tomcat will still generate a JSESSIONID cookie for the client to use, and under most configurations of the container, you can't turn this off. However, if sessions aren't created, the cookie is essentially ignored (and a new JSESSIONID cookie will be generated on every request).
And, because the app is stateless, there is no concept of login or logout. All authentication is done per request.
Note that, depending on your particular app, pragmatism may trump pure RESTfulness. There are cases where "a little bit" of server state is really the only way to provide some types of security to the app (such as cross-site request forgery, anything with nonces, etc.)

If you are doing a RESTful webservice you shouldn't handle sessions.
The first time you connect to the API you need to pass the authentication check in order to obtain an authentication key.
This key is how your API will identify its users.
You shouldn't invalidate the session and you shouldn't force your users to re-authenticate.

Related

Session management in Spring with REST

So I am building a REST-API using Spring for a simple game. I now have the need to be able to track a user together with some data (what games they're in and on what team). I got some tips that Spring security might be worth checking out, however I fail to see how that would help me without necessitating a login.
Are there any good methods for doing this?
I've also tried using the session which can be gotten from HttpServletRequest, however this session differs from the first navigation to the webpage, which I was not able to resolve and I'm worried that it would be too unreliable.
REST is supposed to be stateless. That means you don't really want to have a session for stuff like user data. This should all be persisted server side and managed via rest calls. You would have a User resource and a Game resource and perhaps a relation between them, all held in a database. Spring Security is not going to help you with any of this.
What Spring Security might be able to help you with is securing your REST services and managing identity. Although REST is stateless, it is normal for a client to send something like an access token in a HTTP header. This access token provides both identity and authentication. Again, you will need to separately manage and store the relationship between the access token and the user server side, perhaps in your database.
Session can be fetched from HttpSession and not HTTPServeletRequest. HttpSessions are reliable.

Securing REST api with Token

I have been struggling with this the last couple of days and haven't found a reliable, understandable solution on the web.
I have a web app that is comprised of a rest api and a presentation layer consuming it. Presentation layer has a login form, the data introduced by the user is sent to the REST api which then uses a third party service to authenticate the user. This part I have already set up.
What I want now is to inrtoduce a token-based authentication for every subsequent request so I don't have to send credentials on every request and then authenticate again against the third party service.
So basically, using Spring Security (v. 3.1.3), I am lost as to how to create a reliable, secure token, return it to the requester, then authenticate request based on said token.
Can you point me to the right direction? Or to some example online?
How do you generate the token? How do you return the token to the
client?
How would you send the token in subsequent requests?
How do you set the whole thing up so the first time you can
somehow send the credentials (user/pass) then the subsequent
requests send only the token?
How do you authenticate against the token?
I've seen implementations where token includes some expiryTime. So what happnes after expiryTime is exhausted? The user must login again, even if he's been making requests the whole time? Should I renew the token "behind the scenes"?
Is the server-side REST application stateful or stateless? If stateful, you won't need to do anything special using a regular HTTP Session. Just start using Spring Security and if the client and server are already exchanging session information, your protected API endpoints will work out of the box. The only caveat is if you have CSRF protection enabled, in which case you will need to tweak the client a little bit. Details for this are in the Spring Security documentation.
On the other hand, if the REST application is stateless, you will have to use a token-based approach like you have proposed. See my answer to a similar post for details. If you do choose to follow the steps in that answer, answers to your questions are:
The token has to be generated on the server-side. If you go through the sample code linked to my answer, you will see that I have replaced the default HTTP-session-dependent infrastructure of Spring Security with a cache-based infrastructure. In the session-based implementation, the unique conversation identifier, which is the session ID, is generated by the servlet container, whereas in the custom implementation, the identifier, which is the token, is generated within the application. Specifically, I have used a SecureRandom instance to generate strong tokens.
The token is sent back by the client as an HTTP header. This protects the content over an SSL channel.
The trick is to implement four very simple interfaces from Spring Security. My sample app has full details. The whole process took me less than an hour.
Authentication against the token is done automatically by Spring Security. We simply need to provide an implementation for storing and retrieving tokens, which is straightforward and takes only a few lines of code.
In my sample app I have used an expirable cache with sliding expiration for storing the tokens. If a client keeps sending requests periodically, the server keeps on accessing the cache for the authentication token, thereby keeping the token alive in the cache. Tokens are evicted from the cache only after a period of inactivity equaling or exceeding the cache expiration period.
So overall, a token-based authentication/authorization approach can be easily implemented with Spring Security and leveraging a caching library like EHCACHE.

JSESSION/HTTPSession vs. application-crafted session ID

In a web application based on propraietery MVC and authorization model, we have recently migrated to Spring MVC.
As part of that move, we are also looking at moving away from a locally created GUID that is passed with each request to a cookie based Session ID.
On the face of it, it looks as if in our case, doing so will be a big disadvantage as the standard JSESSION/HttpSession seems to be the root of all security evils:
Session Fixation (In existing code session is only created after succesful login, so we need never invalidate() a sessions.
CSRF - Session is never passed as a cookie so this is never a risk (and god, it's a problematic one to handle since there is no real framework or generic solution out therem checked HDIV and CSRFGuard).
Testing Useability - QA can easily have multiple users with multiple roles connecting to the same Server, not possible with JSESSION.
In consistent HTTPSession creation and invalidation in various Containers (Weblogic, JBOSS and Websphere)
Inconsistent JSession handling when moving between HTTP to HTTPS.
So, other than the obvious advantage of "being standard", Any clues as to why would I want to go the JSESSION route?
Not really a categoric answer about why you should or should not use jsession, but stil some remarks regarding your concerns:
Your application should not rely on the fact that a session exist or not. It should rely on the fact that the session is valid according to certain rules you put on it (user authenticated, roles assigned to this user, etc...)
CSRF is not really a big deal as long as you take care to not use GET for sensible actions, and as you mention Spring MVC, it is quite easy to achieve with it.
True, if you only rely on one browser. And as a side note, while manual testing remains a must for some situations, many use cases can benefit from automation, and thus reduce the impact of having to switch from a role to another.
Never encounter a problem with that. But I tried to kept the content of the session as small as possible.
And that's a good thing. It can prevent you from moving away from your secure connection without noticing it.
Now, whatever the option you'll choose, there will always be some drawbacks. Having a UUID in each request (and thus potentially in each GET URL) does not allow your users to use bookmarks easily. Nor to keep their session alive.
After much discussion analysis and testing, it seems that tleast in my case, a non RESTfull application, with a desktop like RIA UI, and extensive security considration, JSESSION is not the way to go (CSRF mainly) and a better option is a BODY based internally generated key.
This does mean though, that the application will be forced to handle timeouts and session invalidation.

Best way for long-time login with Java Servlets

In my web appication i need to recognize signed in users even if they restart the browser ("Remember me" function of web sites). What is the best practice to achieve this using Java Servlet API?
I've considered the following options:
Using long-term HttpSession sessions and storing user identifier as an attribute of the session. This approach doesn't permit user to restart browser, because JSESSIONID cookie is not persistent and there is no standard way to change its properties. The only option i consider is to use SessionCookieConfig interface of Tomcat 7.0 to tune default JSESSIONID parameters. But there are doubts about the scalability of such solution, because Tomcat will store all sessions for a long period of time.
Using short-term HttpSessions together with some persistent cookie which stores the user identifier with some security hash. When user restarts the browser, it sends persistent cookie and application server binds new session with user identifier.
What is the common way to achieve this?
I have always needed more control over my sessions, because I need them to work across multiple web applications, so I implemented my own solution from scratch. It is pretty easy, just hash a random number and store it in a database. If you don't have or want a RDBMS just some sort of key/value store.
Are you using normal filter-based authentication? How secure does your site need to be?
One way:
Drop a cookie with a code in it on their browser. In Tomcat, have a typical filter configured. The filter grabs the code and checks it against the database for validity. If the code is valid the normal Tomcat authentication is avoided. If there needs to be any persisted session variables, you can load them from the database now.
Drop a new cookie code with every response. It should include a hash of a salt, the user's ID, and the user's IP address. That way the cookie will do no good if the request comes from the wrong computer. Though IPs are spoofable.
Bear in mind, you're short-circuiting security when you do this. You're saying, "Oh look, you've just come out of nowhere. I think I know you! Here, have the keys to my castle!" This sounds like the sort of request we'd get from the marketing folks who didn't understand a thing about security and didn't care since it wasn't there problem if we got hacked.

Client side sessions

I want the clients of several related web apps to hold their own authentication state. This improves scalability, because no session replication between cluster nodes is needed. And it makes integration of different server technologies like Java Servlets and PHP easier.
My plan is as follows:
Set a signed and encrypted cookie with the user name and session expiration time after client authentication.
When the client sends a request, the server decrypts and validates the cookie and grants or denies access depending on the cookie values.
The session expiration will be updated through resetting the cookie.
All servers that want to use the session have only to know the cookie mechanism and the decryption key. See also: Session state in the client tier
Is this approach ok? Would it be possible to integrate it into a servlet container / application Server so that it is transparent to the applications? A servlet should be able to use HttpServletRequest#getRemoteUser() for example. Is this possible? Or would I need something above the container level like Spring Security? Are there any existing libraries for client side session management?
Not a good idea. Storing vital data like session expiry and user name entirely on client side is too dangerous IMO, encrypted or not. Even if the concept is technically safe in itself (I can't answer that in depth, I'm no encryption expert), a break-in could be facilitated without compromising your server, just by acquiring your encryption key.
Somebody who gets hold of the key could generate session cookies at will, impersonating any user for any length of time, something the classical session concept is designed to prevent.
There are better and scalable solutions for this problem. Why not, for instance, set up a central session verification instance that all associated servers and services can poll? Look around on the web, I am 100% sure there are ready-made solutions addressing your needs.
I disagree with the posters saying this approach is not secure. Variants of it are used in a number of well respected frameworks, such as Rails and Play!, for precisely the reasons you outline, and it's perfectly secure when implemented correctly.
This improves scalability, because no session replication between cluster nodes is needed.
First, using HTTP Session doesn't really prevent you from scaling, even when using HTTP Session State replication (some mechanisms are smarter than others by the way, for example WebLogic's in-memory replication doesn't have a big overhead). Second, do you really need it? Most applications (the majority) don't need Session replication. Third, am I understanding right: do you plan to not use HTTP Session at all?
(...) Set a signed and encrypted cookie with the user name and session expiration time after client authentication.
Don't do this! Don't store a username and other sensible data used by the server in a cookie, this is a very bad idea! You actually need to admit that it's just a matter of time before someone figures out how your system works and breaks it (especially if your cookie is candidate for crib attacks). Sor, really, you should store data in the Session on the server-side and only an ID in the cookie, like things are actually working. This is much more secure.
Is this approach ok?
No. And you don't need this for interoperable single-sign on (if this is what you are trying to build). Just use a centralized authentication solution like CASJasig which has libraries for various technologies.
This is not really how Sessions are implemented. The cookie itself doesn't need to carry any data of the session itself, it's just a reference to it.
What the Cookie holds is usually a Session ID which is then linked to the data on the server.
If you don't have a central data session server for the other servers to access, I suggest to get one :).
You can avoid duplication of data in a clustered environment by using a state server - a server that is well known by all the nodes in the clusters and maintains the session data for all the users. Every time a user performs a request, it send a cookie with session id to the applications server; this one should retrieve the session from the state server. This is possible for asp.net development, but I'm not sure how easy Java supports this approach.
As Pekka said, not a good idea. One can intercept your cookie with sensitive session data. Even with SSL, by using fiddler2 one can decrypt the traffic

Categories