I'm having a hard time piecing together the various threads I've read on the topic, so I'd love to know if I'm on the right track before I get too far. I'm trying to make persistent logins using sessions and cookies and the like. At this point, I feel I've got my head around the login sequence, right now I just have a user db, but I'll try to tackle OAuth at a later date.
Login:
User enters credentials
Creds are sent async to server (ideally via SSL, eventually)
Passwords are never stored, only hashes are kept
If creds are OK, server sends the value of this.getThreadLocalRequest().getSession().getId() back
Callback method saves sessionID in a cookie and modifies the UI accordingly
(logout method clears the cookie and calls this.getThreadLocalRequest().getSession().invalidate())
I get lost when I want a user to be able to come back and pick up where they left off without having to log back in. I get the sessionID back from the cookie (if there is one), and then I somehow need to ask the server to verify it's valid. Is there a method that takes a session ID and returns whether it's a valid session? Or do I somehow tell the current session to use that ID?
The end goal is that I want to include the session ID in RPC calls that should be restricted to logged in users, and the server side methods will validate the sid received by RPC before running. I don't have to keep a running list of valid sids, right? That's already being handled by GAE (yes, I have the <sessions-enabled> set)
getSession returns a session object that can be used for persistent storage across requests. It already uses cookies to persist the session ID between requests. You don't need to get the session ID and store it separately in another cookie.
If you want to associate data with the user in the DB, either associate it with the session ID (eg, include the ID in the entity and look it up by ID) if you want it to be scoped to just the current session, or associate it with the user ID.
Unless you have a really, really compelling reason to invent your own user management, though, you really should be using the built in Google Accounts or OpenID support. You're not doing your users a service by forcing them to create yet another account for your site.
this.getThreadLocalRequest().getSession(false)
Returns the current HttpSession associated with this request and returns null in case it has no valid HttpSession.
Related
I understand that token based authentication is widely used for microservices, esp, when there is horizontal scaling.
For microservices also, can we use sessions by storing it in database?
The series of requests would be :
First request, HTTPsession is created and session id stored in a database table along with unique
username.
Second request is sent with this session id, and any
microservice instance can serve this request. Server has to verify
this session and user with that of the database record. If sesssionid+username combo is present in database and sessionid is a valid one, then serve the request else redirect to login page.
When logout is clicked, session is invalidated and db record is also removed.
Will this not be a good session management for microservices?
Do Microservices always have to be stateless?
The reason token based authentication is used for microservices, is to avoid having to share session state between the services.
If you specifically refer to an implementation of the javax.servlet.http.HttpSession object, this is normally local to one server (service) and it would take some custom code to reload this based on the session id provided, if at all possible in your particular runtime (don't know what software you are using).
I don't see why your suggestion wouldn't be possible though, but I would carefully consider if it is an absolute requirement. There might be other, simpler, ways to achieve what you want.
One way of doing it would be to issue a token (JWT comes to mind) when logging in, and having the other services simply verify this token and extract the user data from it. This way no lookup of user data is required for authentication after the first login.
If shared state is what you need, I would suggest finding some existing software to handle the session storage. I see that for instance Redis has a solution for session management.
Also you may check out the answers to this question
I'm using OpenID. How do I make it so that the user stays logged in for a long time even after closing the browser window?
How do I store and get access to the user's User object?
Basically, I guess I just don't really understand how sessions work in Java.
So you actually want like a "Remember me on this computer" option? This is actually unrelated to OpenID part. Here's a language-agnostic way how you can do it:
First create a DB table with at least cookie_id and user_id columns. If necessary also add a cookie_ttl and ip_lock. The column names speaks for itself I guess.
On first-time login (if necessary only with the "Remember me" option checked), generate a long, unique, hard-to-guess key (which is in no way related to the user) which represents the cookie_id and store this in the DB along with the user_id. Store the cookie_id as cookie value of a cookie with known cookie name, e.g. remember. Give the cookie a long lifetime, e.g. one year.
On every request, check if the user is logged in. If not, then check the cookie value cookie_id associated with the cookie name remember. If it is there and it is valid according the DB, then automagically login the user associated with the user_id and postpone the cookie age again and if any, also the cookie_ttl in DB.
In Java/JSP/Servlet terms, make use of HttpServletResponse#addCookie() to add a cookie and HttpServletRequest#getCookies() to get cookies. You can do all the first-time checking in a Filter which listens on the desired recources, e.g. /* or maybe a bit more restricted.
With regard to sessions, you don't need it here. It has a shorter lifetime than you need. Only use it to put the logged-in user or the "found" user when it has a valid remember cookie. This way the Filter can just check its presence in the session and then don't need to check the cookies everytime.
It's after all fairly straight forward. Good luck.
See also:
How to implement "Stay Logged In" when user login in to the web application
How do servlets work? Instantiation, sessions, shared variables and multithreading
Well, the original reason I chose OpenID was so someone else could handle as much of the implementation and security of authentication for me.
After looking into OpenID more, it appears there is something called an "Immediate Request" (http://openid.net/specs/openid-authentication-2_0.html#anchor28).
When requesting authentication, the Relying Party MAY request that the OP not interact with the end user. In this case the OP MUST respond immediately with either an assertion that authentication is successful, or a response indicating that the request cannot be completed without further user interaction.
Because of this I think I could just store the user's openID url in the cookie, and use an immediate request to see if the user is authenticated or not. This way I don't have to do anything with my database, or implement any logic for preventing session hijacking of the long-lived cookie.
This method of doing it seems to be the way OpenID suggests to do it with their Relying Party Best Practices document.
I am using JBoss server. I have one problem with session. After logged in to the page again I restarted server. But user session is getting logged out. Again It redirects to login page. I need to allow user to see the webpage without logout.
After restarting the server, your login session information is lost. You need to persist it to avoid this.
https://community.jboss.org/wiki/HAWebSessionsViaDatabasePersistence looks like exactly this.
When you restart the application server, all the sessions will be terminated, that is a normal thing, because sessions are kept in the memory to put it simply.
If you want the user to continue on from his previous session, you will have to go through a lot of trouble such as re-creating the session objects and populate them with the data you somehow saved from last session, and a way to authenticate the user without the user entering his password again. That is probably the easy part which you can achieve by storing the session identifier in a cookie and keeping track of it in a database or text file, but re-creating the session itself exactly from where you left off might not be a good or even practical idea.
Two options for storing and restoring the session:
1) Save the data related to the session (items in a shopping cart for instance) in a database or a text file of some sort. (save it on the hard disk) This will prove very difficult, how difficult depending on the complexity of your site.
2) Save the users session data in a cookie along with the session identifier (jsessionid). Again you will need to do some custom work, identifying these cookies and reading them. User can always get rid of cookies, or disable them etc.
If you have a very simple web page that doesn't include any data other than the authentication, you simply want to see the previous page you were at, you can save a cookie in the client identifying the user and the page he was last at.
Are the objects serialized and sent to the user and back on each connection (stored in cookies) ?
Or are they stored in the server heap and the cookie is only a very small identifier ?
Any information about this topic would be helpful.
Thank you
You got it on the second guess.
The cookie contains a JSESSIONID. That id is used to look up the user's HttpSession in a map that the server maintains. At least this is the most common way. There are more intricate ways that the server can implement this, but shuttling the entire state back an forth in a cookie isn't one of them.
This has some implications. First, if the server goes down, you lose session state. Second, if you have a server cluster, you need to get the user connected to the same server each time, or they will lose their session between subsequent requests. Lastly, session hijacking becomes a possibility if someone finds a way to copy someone else's JSESSIONID and replace theirs with it.
The cookie just contains a session identifier (typically called JSESSIONID). The server maps this identifier to whatever data is currently stored in the user's session.
The data itself may be stored in memory, or it may be serialized to database or to file depending upon what server you are using and its configuration.
We can enable session by setting sessions-enabled to true in file appengine-web.xml. However, the session implemented by GAE is not persistent after closing browsers. My question is how to keep the session persistent so "remember me" function can be implemented. There are a number of Python libraries but I couldn't find any for Java. Thank you very much for your help!
The common way to do this is to associate a unique random key to your users, store it in a persistent cookie (use Cookie.setMaxAge() with the number of seconds you want this cookie to stay valid), and send this cookie to the user.
Look in the javadoc for HttpServletResponse.addCookie (to send a cookie to the user), and for HttpServletRequest.getCookies() (to get back the cookie from the client).
Since we can't mark a comment as an answer (and some people are likely to miss it entirely), I'll point out the specific solution per JB above. Get the session id using this.getThreadLocalRequest().getSession().getId(). Store the sid in a cookie as JSESSIONID with Cookies.setCookie(...)
This overwrites the cookie created by GAE, keeping the same session id, but applying your expiration time. Be careful how you use this, though, it's prone to attacks (look up session hijacking and XSS).