By browsing through the code of the Auth and Session snaplets I observed that session information is only stored on the client (as an encrypted key/value store in a cookie). A common approach to sessions is to only store a session token with the client and then have the rest of the session information (expiry date, key/value pairs) in a data store on the server. What is the rationale for Snap's approach?
For me, the disadvantages of a client side only session are:
The key/value store might get large and use lots of bandwidth. This is not an issue if the session is only used to authenticate a user.
One relies on the client to expire/delete the cookie. Without having at least part of the session on the server one is effectively handing out a token that's valid to eternity when setting the cookie.
A follow-up question is what the natural way of implementing server side sessions in Snap would be. Ideally, I'd only want to write/modify auth and/or session backends.
Simplicity and minimizing dependencies. We've always taken a strong stance that the core snap framework should be DB-agnostic. If you look closely at the organization, you'll see that we carefully designed the session system with a core API that is completely backend-agnostic. Then we included a cookie backend. This provides users with workable functionality out of the gate without forcing a particular persistence system on them. It also serves as an example of how to write your own backend based on any other mechanism you choose.
We also used the same pattern with the auth system. It's a core API that lets you use whatever backend you want. If you want to write your own backend for either of these, then look at the existing implementations and use them as a guide. The cookie backend is the only one I know of for sessions, but auth has several: the simple file-based one that is included, and the ones included in snaplet-postgresql-simple, snaplet-mysql-simple, and snaplet-persistent.
Related
With a database session token system I could have a user login with a username/password, the server could generate a token (a uuid for example) and store it in the database and return that token to the client. Every request from thereon would include the token and the server would look up whether the token is valid and what user it belongs to.
Using JWT there would be no need to save anything to the database with respect to session/tokens thanks to the combination of the secret key kept on the server and the signed token the client keeps and sends with every request.
This is good but besides saving a database check each request (which would be fast anyway since it's just checking a hash table) it's not clear to me what the advantages are of using JWT. Can you anyone familiar with this explain? Let's ignore cookies, it's specifically a database custom token as described above and JWT that I am trying to compare and understand the benefits.
The main difference is the session storage size and lookup work required from the server:
On the server side, JWT stores a single key in memory (or in config file) - called secret key. That key has two purposes, it enables creating new encrypted tokens and it also functions like a master key that "opens all locks", in practice it verifies all tokens.
As a result the server responds much faster to auth requests, because it doesn't matter if you have two or two million users logged in - the same number of records (one, that server key) will be used to authenticate all client requests.
Traditional authentication that stores user sessions in a database, creates a record in the db for every single user, which results in multiple keys.
So if you have two million users logged in, the server will create two million records and with each client request the server needs to locate the relevant session record in the database*.
JWT leaves it up to the client side to store and handle the entire session/user object. It actually makes much more sense because every client handles their own data only, so it doesn't cause heavy lifting for the client side either.
As for what you wrote in your last paragraph, it's not just db calls that we save here. JWT is actually much more scalable because of its independent and lightweight nature, it doesn't fail as auth requests pile up and it allows the server to handle auth accross devices and services without managing sessions on the server side.
Security wise though, db sessions arguably have the upper hand: they can be more secure because of that latency, and are also less vulnerable to session hijacking after user logout.
*The db stored sessions method can be optimized with effective caching and by storing only the session id (as opposed to the entire user object) in a fast key/value server such as Redis. That said, I would still choose JWT method over db for most cases.
A Json based token(JWT) overcomes the following problems:
Mobile issues: Native mobile apps seems to have problems working with cookies so if we need to query a remote API, maybe session auth is not the best solution.
CSRF issues: If you are following cookies way then you need to have CSRF to avoid cross site requests.
But JWT doesn’t use sessions, has no problems with mobile, it doesn’t need CSRF and it works very well with CORS too. If you dont have a valid token you can't do anything.
One more as this token gets stored at client local storage/session storage so you can pass these tokens to other clients as well but you have to share the same credential which you used to generate this JWT.
You are underestimating impact of the database call. Database connections are expensive and round trip takes time. If you are doing thousands of requests per second. Your database would be bogged down with just authentication related queries. In that case not only will it be slow, the query can altogether fail. Even if you use something lighter and faster like redis, it won't be more robust or faster than not making a call at all.
The JWT alternative eliminates all this. The auth can be done without a network call to and response would be sent in milliseconds.
It seems to me that as long as you only want to store simple values like a timestamp for last visit and maybe a userid in the session, there's really no point at all in using Redis as a session persistence with Gorilla sessions since they seem to be storing it in cookies on the client side anyways.
Am I correct or not in this assumption?
I understand that there's a size limit and also that if I were to store sessions on file (the other available storage option with gorilla sessions), it'd be impossible to scale beyond that machine but again, is this whole "session store" a non issue with gorilla sessions cookie store?
Btw, I've seen this question here and NO it doesn't address this issue so it's not a duplicate. What is the advantage of using Gorilla sessions custom backend?
Using Redis (or any other server-side store) can help avoid a whole class of problems, namely:
Large cookie sizes adding per-request overhead - even an additional 4K per request can be a lot on mobile connections.
Severely reducing the risk of cookie data being manipulated as it is stored server-side.
Ability to store more than 4K in the session (i.e. form data from a multi-step form)
... and in Redis' case, the ability to easily expire the server-side sessions (something that's more error prone with mySQL or a filesystem store.
A cookie is still required as it must store an identifier so the user can be associated with their server-side session. This isn't particular to gorilla/sessions whatsoever and is how nearly all other server-side session implementations behave.
If you think your use case is simple then sure, stick with cookie-based sessions. gorilla/sessions makes it easy enough to change out the backing store at a later date.
I have 2 osgi distributed web apps A(A1, A2) and B(B1, B2), i am using shiro to share the http sessions for single sign on so that logginng in one system logs in the other too. But I want the session data to be separated between system A and B apart from the authentication/authorization data,so I need a way to share the authentication data and separate system specific session data of A and B. I am thinking to use shiro for single sign on and use a different distributed session for each system to store system specific data, the main workflow would be :
log in system A with shiro, create an another session(or some data holder object to store the session data) using the shiro session id,stores it in backend(db or cache).
do stuff in system A, put session data into the session created above, writes to backend.
When another request comes in system A, look for a session with the id matching the shiro session id, if found, use it, else create new one.
Does it make sense? Is it the right way to solve my problem? What is the best way? Please share your thoughts.
Any input is appreciated.
Thank you.
I've done something like that with a Servlet Filter. My HtppSession contains the authorization id which I then lookup and provide as security context for the request. If no security id is present, the client is forced to login. Obviously the security context can be held in a distribution mechanism so it is available from all systems in a cluster.
Make sure you use https between the client and the systems or otherwise someone can eavesdrop, read the cookie with the id, and login to one of the systems with the authorization of the victim. I.e. session hijacking.
I am implementing DotNetOpenAuth for both an OpenId provider and a relying party. In both cases, the servers are behind a load balancer, so for any HTTP request, we can't assume that we'll hit the same server.
It appears that DotNetOpenAuth depends on the Session to store a pending request key. Because the server may change between requests, we can't depend on the standard InProc Session. Unfortunately, we've been unable to successfully implemented SQL as the store for Session.
My question is: is it safe to store a PendingAuthenticationRequest as a client cookie? Any worse than using Session?
The ProviderEndpoint.PendingAuthenticationRequest property is there for your convenience only, primarily for simpler scenarios. If it doesn't work for you, by all means store it another way and totally ignore this property. No harm done there.
Ultimately a session is tracked by an HTTP cookie, so you can certainly store the auth request state entirely in a cookie if you prefer so that it works in a web farm environment. Another approach is to not require the client (or the server) to track state at all by either making everything (including authentication) handled directly at the OP Endpoint URL, or redirecting the user from the OP Endpoint URL with a query string that includes all the state informaiton you need to track. Be careful of the latter approach though since you'll be exposing your state data to the user to see and possibly tamper with.
In short, you may or may not choose to store user sessions in a SQL store. That should be fine. The issue I think you ran into (that we discussed by email) was that you needed to implement your own IProviderApplicationStore, which will store nonces and associations in a database that is shared across all your web servers. This is imperative to do, and is orthogonal to the user session state since this is stored at the application level.
I was once in a project of web application developed on ASP.NET. For each logon user, there is an object (let's call it UserSessionObject here) created and stored in RAM. For each HTTP request of given user, matching UserSessoinObject instance is used to visit user state information and connection to database. So, this UserSessionObject is pretty important.
This design brings several problems found later:
1) Since this UserSessionObject is cached in ASP.NET memory space, we have to config load balancer to be sticky connection. That is, HTTP request in single session would always be sent to one web server behind. This limit scalability and maintainability.
2) This UserSessionObject is accessed in every HTTP request. To keep the consistency, there is a exclusive lock for the UserSessionObject. Only one HTTP request can be processed at any given time because it must to obtain the lock first. The performance and response time is affected.
Now, I'm wondering whether there is better design to handle such logon user case.
It seems Sharing-Nothing-Architecture helps. That means long user info is retrieved from database each time. I'm afraid that would hurt performance.
Is there any design pattern for long user web app?
Thanks.
Store session state in the database and put memcached in front of it.
One method discussed on StackOverflow and elsewhere is the signed cookie. A cookie that has information you would otherwise not be able to trust, along with a hash created in such a way that only your server could have created it, so you know the information is valid. This is a scalable way to save non-high-security information, such as username. You don't have to access any shared resource to confirm that the user is logged in as long as the signed cookie meets all criteria (you should have a date stamp involved, to keep cookie theft from being a long term issue, and you should also keep track that the user has not authenticated, so they should have no access to more secure information without going through the usual login process).
StackOverflow: Tips on signed cookies instead of sessions