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.
Related
I have been trying to read through existing information about this topic. I even installed KeyCloak server locally, configured the realm, the client and used Postman to send some requests to KeyCloak, and received some json response.
My problem is that - unless I misunderstand something - none of the descriptions seem to fit my goals.
Our application already has user management and we rely on user identity and roles / access rights configured in the system. The backend runs inside Tomcat and we run a Polymer 1.0 / Javascript frontend to call the REST services of our backend. I cannot get rid of user management as our DB is highly dependant on user to object assignment when deciding the scope of the objects for which the particular user is responsible.
All we need is an extension of our system by the possibility of foreign authentications (like social logins) in the future.
We have now explicit login that delivers a session cookie, Servlet filters to check the presence of this cookie, etc. In the server we use the login token / user identity in each REST call to filter the results from the DB to those available to the particular user.
What I need is a flow like:
in the fronted we check if we have active session (existing code)
if not we redirected the user so far to our own login page, logged in, created the session cookie on server and then returned it. On client side we saved this and added to every REST request as authoriation token.
Now with OIDC I'd like to insert a new unprotected query that checks if OIDC is configured. If not, we keep the old solution. If yes, I'd like to get redirected to KeyCloak login, and - and this is the most important for me - I'd like to get back the user identity (or some role that we associate administratively to the user - using which I could identify one of our configured users.
I tried experimenting with the Tomcat solution but that simply blindly hides the authentication procedure and merely allows or blocks REST access to the backend resources. This is not enough for me, I need some kind of user identity which I can use in the server side.
Also a javascript solution only provides communication between frontend and keycloak, but we need the backend to know who has logged in.
I think this topic and all the used lingo is too complicated for me. Could anyone give me some easy advice how to solve this with best practices?
Thank you very much
I have web client which invokes multiple services. As soon as the user is authenticated, I want to store the email Id somewhere as it sends the email Id for each request.
I don't want to use session as I have heard that is the best practice. In REST, all data must be sent for the request and it must be stateless. What other alternatives are there? Is using DB for session management still not breaking the stateless principle of REST?
I went through If REST applications are supposed to be stateless, how do you manage sessions? but there were many contradicting opinions there. Should the email Id be stored in session storage of the browser then?
I think you should do it with a authentication header. Check out these threads:
Do sessions really violate RESTfulness?
If REST applications are supposed to be stateless, how do you manage sessions?
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.
On my web app using Java EE 6. I want to expose some of my functionality as a Json Rest Service. I want to use authentication tokens for login, User will send their username, password and server will send back a token, which will be used to authorize the user on their further requests for a given time..
A few questions bothering me so far;
When the server creates the token and sends to client, should server save it in a DB OR in a Bean using something like a hashtable as userid-token pairs?
Can I get some help using any Java EE specific API or this has to be all custom code?
Heres my input:
I would save the token in DB, in case you need to restart the server you don't want to lose all your user's tokens. You could potentially save it in memory as well to speed up requests and only look it up in DB if it is not found in memory.
I would accept the token in the header. I would put the rest service on HTTPS so the request is encrypted and then you don't need to worry about encrypting the token manually in the request
I would probably look at JAX-RS and see what features it offers
I recently blogged on how to set up Role-based authorization in a JAX-RS REST API using both a simple session token approach and a more secure method of signing requests using the session token as a shared secret.
It boils down to:
Get a session token from the server along with some identifier for the user
Use the token to encrypt the information in the request
Also use a timestamp and nonce value to prevent MITM attacks
Never pass the session token back and forth except for when retrieving it initially
Have an expiry policy on session tokens
Saving the token in a bean or hash table would not be persistent. A DB would persist between executions.
If you are going to be using REST then you can either pass the authentication in the parameters to the method, or in the request header itself. Encryption is a different matter. I guess it depends on the scale of the system, and how open it is. If security is a top importance, then yes, you should find some form of encryption.
I have done similar things using the Spring Framework, and Spring Security. These things are relatively simple using this. To write custom code is to reinvent the wheel. There are many frameworks out there which will help you. However, you would then have the learning curve of the framework.
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.