I am working on Spring 4 mvc application with mysql database, tomcat server.
Basically, I am creating a Spring rest which will be used by Angular JS.
Note: I am not using Spring security
In order to avoid session replication in case of clustered environment, I am using cookie approach.On login, I am generating one unique session id (using java UUID) and use it to create a cookie and then set the cookie in the response.Also, storing that session id in database along with any user data.
In order to authenticate every rest API, I have written a Spring interceptor which will intercept every rest API call which in turn check if there is a cookie in the request.If it is present, I am fetching session id value and using it, making a database call to check if it is valid or not. On logout, I am deleting the cookie.
Base on what i am doing as explained above, I have few questions:
1) Is my approach correct? or do you see any flaw in it.
2) Let me know if there is any other better method to achieve the same i.e. to avoid session replication.
3) Since, I am not using any HTTP session, how do I achieve something like session-timeout or do i even need it?
1) Is my approach correct? or do you see any flaw in it.
Its a good approach. Just a couple of points though in order of precedence:-
If you are using your API to service alot of requests then think about using in-memory cache rather then DB. Going to DB is relatively much more expensive. Alot is subjective I know and it depends on your setup, but just consider the DB for data you want to live beyond sessions. Better to use a more temporary/faster store such as an in-memory cache for things like API tokens. If across a cluster then explore a distributed cache solution.
Using cookies is not necessarily a security risk but have a bit of a read about CSRF. More secure to pass the token in a HTTP Header rather than in the cookie itself - that is if you are concerned about CSRF (I do use the Header approach in my own apps but I think CSRF is relatively rare and it depends on how sensitive your data is)
2) Let me know if there is any other better method to achieve the same
i.e. to avoid session replication.
Nothing to add over response to 1.)
3) Since, I am not using any HTTP session, how do I achieve something like session-timeout or do i even need it?
Store (preferably in cache) a timestamp with the token, and refresh it in the cache for each transaction that uses the token. Then, when checking if you consider if the token is valid, check the timestamp and you can decide (based on time elapsed) if you wish to remove the token and request the client to re-authenticate.
Related
We have a spring-boot appplication with microservice architecture.
We have a separate service for Authentication which provides a JWT token signed with RS256 algorithm.This token is sent in every request from client to our main application server.
I have the public key for verifying the signature.
Now this JWT token is being sent in every API request from client side as most of our URLs are protected.
Is it a good idea to cache the already verified JWT token to prevent repeated verification process of same token on every API call from same user?
There can be good reasons to cache token validation results. I would only do it if necessary, since in memory validation is fast.
Sometimes, after validating the token and identifying the user, you may want to do a fairly expensive lookup of roles etc - and you don't want to do this on every single API request
If caching then store a SHA256 hash of the token - and set a time to live no greater than the token's exp claim, as Ankur indicates.
My post explores this topic further.
API Gateway solutions often use this pattern. For example, AWS API Gateway allows you to cache a policy document that is quickly looked up when the same token is next received.
You can cache the JWT token but you have to set the cache timeout which should be equivalent to token timeout.
The main purpose of JWT is that of not having server-side state
This means that the server will not store any information, nor will the session.
If you cache your JWT, then your server has State.
You may have trouble later when you wanna scale-up your application(have multiple instances) and you may also face some security issues.
If you insist on the stateful server, then it's better to use cache servers like Redis, And notice that the existent time (lifetime) of each row (each JWT) must equal to its expiry date.
By standards, it's not a good idea to cache JWT in your server(it's
not a good idea to make the server stateful)
This wouldn’t necessarily add security issues, but you need to make sure that your cache stores verified JWT data only for as long as that token is valid. Otherwise, you are gonna have problems terminating sessions. Additionally, I’d recommend using LRU caches for this reason, so that you don’t have to store tokens that are not actively used at this point in time.
#Mehrdad HosseinNejad claimed that caching tokens adds statefullness. However, I would not say it is a critical issue in this case, since other servers that have not cached JWT in memory can still verify the JWT. The issue with scaling up is that cache may grow too large and consume too much memory on each server. Once more, I don’t believe it is much of an issue either, if LRU cache is used with proper parameters. The final suggestion in his answer is to use Redis. While it could be a good advice, it might be a slight overkill, considering the additional network latency. In-memory caching is always going to be faster, no matter what. Having said that, Redis is an extremely viable solution, if you want to avoid individual servers re-doing verification, if another server has already done that.
I have two war files such as war1 and war2
If am login the application, the session will be created in war1 and from that if am navigate to war2, there i need the same session data.
I tried crossContext=true in context.xml of server from that i can access the data by storing it in servletContext.
But the issue is once i logined the screen in chrome the session data will be stored in servletContext and the data will maintain till the application is running.
If am giving the same URL in another browser like IE here also, i can get the servletContext data so instead of navigate to login page the corresponding screen will be opened
Kindly suggest me how can i overcome this issue in java?
Is there any way to findout browser switching or incognito window mode of the browser in java?
Note: am using tomcat server
I have never dealt with your exact configuration problem, but even if you can make this work on a single Tomcat instance, you might have problems should your two web applications ever be distributed across multiple Tomcat instances.
So, I am going to suggest that you actually use a database to store state which needs to be passed between the two applications in a safe and reliable way. Note that the database approach also scales nicely in a distributed environment, so long as you have a single logical database.
While session replication indeed can be done in Tomcat (see here) I really suggest you to avoid this type of issues by eliminating the session altogether.
This session replication is an approach that was somewhat common before ~15-10 years, but nowadays when we have a lot of servers running in parallel to serve user requests and have elastic clusters, this approach is not good enough because basically it doesn't scale well.
There are many ways to achieve what you want, though:
Use a shared database to store the session information. Add some session Id to the response and require the client to pass this id back into all subsequent request along the session. Then execute a query to the Database by this Id and retrieve all the session information.
This solution also doesnt really scale well, but then you can shard the session information if the db permits to do so...
Use Redis/Aerospike to save the session information of the currently connected user. somewhat like DB approach, but since redis run in-memory it will be much faster. In general, this approach can be used in conjunction with 1 where redis is an in-memory cache.
Encrypt the session information or even just sign cryptographically and send back to client. Client will have to supply this information along with the request without knowing which server will actually serve this request.
Without delving into cryptography I'll just state that encryption can be done if you don't want client to see the session information (despite the fact that this is the user whose information is supplied) and signature is used to prevent tempering the data (while sending it back to server).
The data can be supplied to server from client via Header or cookie for instance.
What is best practice to validate if a user can be authenticated against a MarkLogic server (version 7.0.4) by using the Java Client API (2.0.4) for a login dialog securing a Spring web application?
With my current approach (see source code in gist) I am implementing a AbstractUserDetailsAuthenticationProvider from Spring Security ("classical" approach with HTTP sessions) where I do create a MarkLogic DatabaseClient instance, after which a simple query (testQuery, L. 46 in MarkLogicConnections) gets executed to see wether a result can be retrieved. From this result is is decided wether the login is granted or not.
I am wondering if there does exist a more elegant solution, but couldn't find anything in the MarkLogic documentation.
You could use that opportunity to retrieve any user-specific data you're storing in the database.
If that isn't desirable, maybe there's no need to verify the user credentials at all? You could let that happen lazily on the first necessary query. And you should be prepared to handle database errors everywhere, in any case.
If you do need a non-lazy verification and don't want any data, that call to suggest() might be more expensive than you'd like. If so you might consider other options. A call to getErrorFormat ought to be fairly cheap. Opening a transaction and then rolling it back should be cheap too, but it requires the rest-writer or rest-admin role. If nothing else works you could write an extension that implements a noop XQuery, probably just ().
I've read that the play framework solves the session fixation issue by hashing the session id with the application key, but does it provide any mechanism to prevent session hijacking, or is this left up to the implementor?
The play documentation has a good section on security, so rather than duplicate, here is a link - http://www.playframework.org/documentation/1.2.4/security.
It covers
XSS
SQL Injection
Session security
Cross site request forgery
Some you have to implement yourself, others you don't.
Your specific question about session hijacking is automatic.
The session is a hash of key/values, signed but not encrypted. That
means that as long as your secret is safe, it is not possible for a
third-party to forge sessions.
No, there is no built in way to prevent the hijacking of a session as soon as one is able to capture the session cookie (through sniffing/man in the middle).
There are some ways to make it harder, e.g.:
using only https
setting application.session.httpOnly in application.conf
One approache to make it harder is:
- store the ip/user-agent/resolution/other stuff or a hash of that also in the session.. in your controller you then check if the user that accesses your site still recreates the same hash... the only real problem is with people that are using a proxy that e.g. changes the ip on the fly because of clustering.
A little trick you could try to use: (works only in recent browsers)
When a user logs in, store some stuff in a HTML5 local storage. Modify your Ajax calls to supply this information from the local storage. If the information is missing/invalid, you can invalidate the whole session. But you'll have to make sure, that the checks only get applied against requests from HTML5 browsers.
hope this helps a bit.
I'm currently implementing a REST web service using CouchDB and RESTlet. The RESTlet layer is mainly for authentication and some minor filtering of the JSON data served by CouchDB:
Clients <= HTTP => [ RESTlet <= HTTP => CouchDB ]
I'm using CouchDB also to store user login data, because I don't want to add an additional database server for that purpose. Thus, each request to my service causes two CouchDB requests conducted by RESTlet (auth data + "real" request). In order to keep the service as efficent as possible, I want to reduce the number of requests, in this case redundant requests for login data.
My idea now is to provide a cache (i.e.LRU-Cache via LinkedHashMap) within my RESTlet application that caches login data, because HTTP caching will probabily not be enough. But how do I invalidate the cache data, once a user changes the password, for instance. Thanks to REST, the application might run on several servers in parallel, and I don't want to create a central instance just to cache login data.
Currently, I save requested auth data in the cache and try to auth new requests by using them. If a authentication fails or there is now entry available, I'll dispatch a GET request to my CouchDB storage in order to obtain the actual auth data.
So in a worst case, users that have changed their data will perhaps still be able to login with their old credentials. How can I deal with that?
Or what is a good strategy to keep the cache(s) up-to-date in general?
Thanks in advance.
To me it looks like you've grown up far enough to use some "professional" cache solution (e.g. EHCache). All distributed caches allow new data replication & invalidation among different nodes so your problem is already solved.
A distributed in-memory cache like memcached might be what you are looking for. You can configure object age, cache size and also expose callbacks to remove specific objects from the cache (like when the information is stale).