The offical documentation states the following about deleting a users cookie:
Link
DELETE /_session
Closes user’s session by instructing the browser to clear the cookie. This does not invalidate the session from the server’s perspective, as there is no way to do this because CouchDB cookies are stateless. This means calling this endpoint is purely optional from a client perspective, and it does not protect against theft of a session cookie.
I can invalidate the cookie on the client but what if somebody siphons the AuthSession=123abc and uses it on the quiet? Isn't this a security problem?
I would like to know how I can avoid this behavior and really destroy the cookie because I would like to have a somewhat secure application with CouchDB.
I'm certain I've answered this question before, but I can't find the duplicate question, so here goes again:
The cookie is a simple hash of the user's login name, the time the cookie was created, the user's password salt, and the server's secret.
This means that to invalidate an existing cookie, you must either wait for enough time to pass that the created timestamp is far enough in the past that the cookie is not considered valid, or change one of the other parts of the hash.
In effect, this typically means it's impossible, because:
Changing the user name means the user will no longer be able to log in.
Changing the user's password salt will also mean the user can no longer log in, unless you also store the user's plaintext password, so that their password hash can be re-calculated. (probably a very bad idea)
Changing the server secret will render all sessions invalid for all users, not just the one you're targeting.
If invalidating active sessions is a hard requirement of your application, it's best done in a reverse proxy server that handles authentication, and uses proxy authentication to interact with CouchDB.
Related
We have React Native app that uses Cognito for authentication. We would like to prevent the same user ID from logging in simultaneously from multiple devices.
We were hopefully that we could use a Cognito pre-authentication trigger for this. Unfortunately it seems that we can't just call globalSignOut for the user since that wouldn't invalidate tokens that have already been issued and are currently active (see https://github.com/amazon-archives/amazon-cognito-identity-js/issues/21#issuecomment-331472144).
The other idea was to reject the login if the user is logged in elsewhere. But we can't see a reliable way to tell whether the user is already logged in. We can see if there are valid tokens issued for that user but not if they are currently associated with an active session.
We also thought of maintaining our own DB of active sessions but there is no sign-out trigger so we wouldn't know when to remove a session from the DB.
You can use a token authentication system,
Issue a brand new token for each login, and check for available tokens.
if any token is available for the user that means He/She is logged in some other device, for this case you can prompt user that You are logged in other device.. are you sure you want to log out from that device ? and after clicking yes, you can clear all tokens for that user. And issue a brand new token.
AUTO LOGOUT : this token should be passed all over the back-end i.e. in headers of each and every API call token should be there... and should be checked before doing anything in back-end. if token is not available then throw 401. In your app if any API throws 401 then it means user is UNAUTHORIZED and should be logged out.
or
your app should be listening to one socket that responds to log out when it receives a message of same. so whenever your user logs in, a logout message will be passed across sockets and appropriate device with some token id or unique id will get that message and will log out a particular user from all other devices.
or
have a notification receiver which will be used to log out whenever necessary same as socket.
Reading the link you provided the API token / session system seems being faulty by design since long time already.
So without an own token-system inside cognito you won't have reliable results probably, at least in the current state of the system (as the repository is archived it won't be developed further by the owner).
What I propose is an own field in the database-table for users where each login is honored with an own token. A second own field in the same table with a timestamp, where the last access is saved.
If last access is older than a predefined time of 30, 60 or 120 minutes any user gets logged out.
If the last access is younger than the time-limit then the login-mask has to provide a random access token which is compared with that in the database:
- if the access-token in the database is too old for an active session, or just no access-token is stored, then access can be granted which means login is successful.
- the comparison of the current time with the time-stamp saved in the database is for cases where users never have been logged out by purpose but just by being disconnected or passive. I think this case will happen regularly, so it's no exception.
- logging out by click on a button should destroy the access-token in the database, so that the user can immediately login from any device, even from another one then before.
- if there exists a valid access-token in the database then no new access will be granted and the user should get shown a message that he has to sign out first at another login.
- The access-token could be stored together with a third own field for the session-id to make it more reliable and safe. On logout that session-token-field can be cleared too. The session-token can be copied from the global session if required to be saved in the user-record.
- Any checks are only done on login, tokens never have to be included on every page.
- On active logout the token(s) have to be destroyed to allow a direct login again, else the users had to wait till the max. age of the time-limit is reached to login again - at least on another device then before.
As the login itself is currently done independent from the check that has to be implemented, it would be possible to leave the new access-token completely away but use only the session-id as that differs on any device and browser. But perhaps there exists a situation where one of session-id and access-token can change but the other one not - I don't think so but perhaps I missed something in my considerations.
If you provide the access-token on every page like proposed by #Jadeep Galani or in a cookie - beside the corresponding check - you also can offer a button to sign out from all devices. This would enable the users to change login any time even without logging out at the last used device. Without access-token on every page or in a cookie this general logout-function solution is not possible as else access is only checked on login but not on all pages.
A general question is if it's still worth it to rely on the buggy cognito for login or just replace it completely by an own solution. You even could implement the desired authentication in your site in form of a wrapper-class and the concrete login-system could be replaced without changing that implementation.
You can use the UUID of the device to identify whether it is the same user. Add a UUID to each request header to record it in the DB, and then you can do what you want.
My web application's authentication mechanism currently is quite simple.
When a user logs in, the website sends back a session cookie which is stored (using localStorage) on the user's browser.
However, this cookie can too easily be stolen and used to replay the session from another machine. I notice that other sites, like Gmail for example, have much stronger mechanisms in place to ensure that just copying a cookie won't allow you access to that session.
What are these mechanisms and are there ways for small companies or single developers to use them as well?
We ran into a similar issue. How do you store client-side data securely?
We ended up going with HttpOnly cookie that contains a UUID and an additional copy of that UUID (stored in localStorage). Every request, the user has to send both the UUID and the cookie back to the server, and the server will verify that the UUID match. I think this is how OWASP's double submit cookie works.
Essentially, the attacker needs to access the cookie and localStorage.
Here are a few ideas:
Always use https - and https only cookies.
Save the cookie in a storage system (nosql/cache system/db) and set it a TTL(expiry).
Never save the cookie as received into the storage but add salt and hash it before you save or check it just like you would with a password.
Always clean up expired sessions from the store.
Save issuing IP and IP2Location area. So you can check if the IP changes.
Exclusive session, one user one session.
Session collision detected (another ip) kick user and for next login request 2 way authentication, for instance send an SMS to a registered phone number so he can enter it in the login.
Under no circumstances load untrusted libraries. Better yet host all the libraries you use on your own server/cdn.
Check to not have injection vulnerabilities. Things like profiles or generally things that post back to the user what he entered in one way or another must be heavily sanitized, as they are a prime vector of compromise. Same goes for data sent to the server via anything: cookies,get,post,headers everything you may or may not use from the client must be sanitized.
Should I mention SQLInjections?
Double session either using a url session or storing an encrypted session id in the local store are nice and all but they ultimately are useless as both are accessible for a malicious code that is already included in your site like say a library loaded from a domain that that has been highjacked in one way or another(dns poison, complomised server, proxies, interceptors etc...). The effort is valiant but ultimately futile.
There are a few other options that further increase the difficulty of fetching and effectively using a session. For instance You could reissue session id's very frequently say reissue a session id if it is older then 1 minute even if you keep the user logged in he gets a new session id so a possible attacker has just 1 minute to do something with a highjacked session id.
Even if you apply all of these there is no guarantee that your session won't be highjacked one way or the other, you just make it incredibly hard to do so to the point of being impractical, but make no mistake making it 100% secure will be impossible.
There are loads of other security features you need to consider at server level like execution isolation, data isolation etc. This is a very large discussion. Security is not something you apply to a system it must be how the system is built from ground up!
Make sure you're absolutely not vulnerable to XSS attacks. Everything below is useless if you are!
Apparently, you mix two things: LocalStorage and Cookies.
They are absolutely two different storage mechanisms:
Cookies are a string of data, that is sent with every single request sent to your server. Cookies are sent as HTTP headers and can be read using JavaScript if HttpOnly is not set.
LocalStorage, on the other hand, is a key/value storage mechanism that is offered by the browser. The data is stored there, locally on the browser, and it's not sent anywhere. The only way to access this is using JavaScript.
Now I will assume you use a token (maybe JWT?) to authenticate users.
If you store your token in LocalStorage, then just make sure when you send it along to your server, send it as an HTTP header, and you'll be all done, you won't be vulnerable to anything virtually. This kind of storage/authentication technique is very good for Single-page applications (VueJS, ReactJS, etc.)
However, if you use cookies to store the token, then there comes the problem: while token can not be stolen by other websites, it can be used by them. This is called Cross-Site Request Forgery. (CSRF)
This kind of an attack basically works by adding something like:
<img src="https://yourdomain.com/account/delete">
When your browser loads their page, it'll attempt to load the image, and it'll send the authentication cookie along, too, and eventually, it'll delete the user's account.
Now there is an awesome CSRF prevention cheat sheet that lists possible ways to get around that kind of attacks.
One really good way is to use Synchronizer token method. It basically works by generating a token server-side, and then adding it as a hidden field to a form you're trying to secure. Then when the form is submitted, you simply verify that token before applying changes. This technique works well for websites that use templating engines with simple forms. (not AJAX)
The HttpOnly flag adds more security to cookies, too.
You can use 2 Step Authentication via phone number or email. Steam is also a good example. Every time you log in from a new computer, either you'll have to mark it as a "Safe Computer" or verify using Phone Number/Email.
We are using WSO2 IS as our enterprise identity platform. One of our tenants must restrict the number of concurrent sessions per user for security reasons.
The expected behaviour is the following: when a user logs in, if he/she already has logged in previously and the session is still valid, the new session must overwrite the previous one, so the login ends ok and he/she gets logged out from the first device/browser. Summing up: the new session always invalidates the old one.
I've been researching sites like this or http://soasecurity.org/ searching for answers, but I couldn't find any.
I think that I need to store the WSO2 IS session id (the one that comes in the commonauthId cookie and gets stored in session cache/persistence store) in the user store, so I can check what's the current user session and log out the user if the cookie id and the store id don't match. But there are two main concerns:
Where do I store the user session id? My main user store is LDAP, but I'd like to avoid one extra attribute there, because it's shared with many other applications and promote changes like this could be difficult for many reasons. Is there any way to put this data into a secondary store?
What's the most appropiate extension point in WSO2 IS to add code for storing the session id in a user store? I've been looking through the authentication framework and found that the method concludeFlow in DefaultAuthenticationRequestHandler class is where new sessions are created when there isn't a previously cached one available. It seems a bit "tricky" to extend that method, but I couldn't find a better solution. Maybe you can customize the authenticator or the user store, but I think that's not a good point of extension inside the authentication flow, because the new sessions are created later, in the request handler.
Thanks in advance.
The WSO2 identity server actually doesn't care about the number of open sessions. IMHO the identity server is not the best enforcement point where to check for the open sessions. Once the user is already logged in, you don't have much control over the framework and the user assertions (or an Oauth token) are returned.
Where do I store the user session id?
If you enable the session persistence, the session information (user session, saml SP sessions, ...) are stored in the database. However - it is intended for internal use. If the user logs out or closes the browser, the records may be still there. There's no information about the user web session.
Just a hint - we've used a VPN proxy (Juniper SA as SP) and WSO2IS as IdP to enforce a unique user session (for a new session the old one is invalidated).
Have fun
Conceptually, I really like JWT as it is in line with the statelessness of REST etc (no state saved server-side, all relevant data is contained in the token).
What I am unsure about: how would you handle token expiry when not connected (ie, a "remember me" functionality)?
There's an emerging coverage of JWT on the web, but I couldn't find anyone that answered the expiry question yet.
Clarification: I am not asking how to handle a token soon-to-expire, but what to do when a token has already expired (user closed website/app for a while). The simplest solution that comes to my mind is caching the user's credentials, which is rather insecure.
There isn't a black and white answer to the given problem of how to implement the remember-me functionality theoretical wise. Lots of theoretical arguments are given on why something should not be done, while at the same time there is no clear answer given to the problem as for how it should practically be done.
Remember-me implicitly comes with the problem that you need a longer time window of token expiration, there is just no way around this. The most secure way is to have the user login regularly given brief expiry; nobody practically likes this though, so a tradeoff is made where theoretical secure perfection is weighed against practical measures.
The way this tradeoff works is by patching the imperfections that come with having a long expiry for a token. But make no mistake about it, you will need a jwt / cookie with long expiry (whether you use two tokens, implement some secondary refreshing mechanism or whatever, at the end you run into the same problem)!
Based on articles I've read on how others did it, this is how it's done.
The way I will implement this is by offering a 3-month expiry on a jwt stored in an httpOnly / secure cookie when the user checks remember-me.
On logout just clear the cookie.
Obviously protect using https / CSRF measures on top.
If you don't agree with it, stop fussing and offer an alternative solution - which there clearly isn't from the infinite number of discussions I've read on it.
If there were a straightforward solution to the problem, there probably wouldn't be so many discussions about it in the first place.
Edit:
You can use a refresh token mechanism, but it only works if you verify the time intervals when the refresh token gets used. For example, depending on the lifetime of the access token, you can govern how often you allow a user to refresh the token. If the intervals show suspicious activity, you should revoke both the tokens for all clients.
The problem revolves around the idea that either access token or refresh token would theoretically be stolen. So merely having a refreshing mechanism without additional security is essentially useless. If you can steal an access token, you can steal a refresh token too.
I am not so sure if I follow but I will write what I think.
Imagine the token as a hotel card, you pay in advance for 5 days (remember me set to expire on 5 days). I can enter the building, garage, room, etc. within those 5 days, after those 5 days, it won't work anymore.
What to do when token has already expired? Nothing at all.
Imagine I pay those 5 days and meh, I had an urgency and I go back home (with the card on the pocket). The hotel doesn't care at all, when the 5 days pass, the card is just an useless piece of plastic and if you try to use it on the hotel, it will do nothing.
So back to web development. If you offer a remember me service, you can put an expiry date to let's say 7 days. As long as the user has the token, he can access the service without any problem. If he loses the token, he needs to login again. If he uses the token and it have expired, he will need to login again too.
If he login, he gets a token for 7 days, if he doesn't use it anymore and after 20 days he comes again, he would need to login again, the server will just decline your petitions until you do so.
What I would do if you use something like angular on the frontend is to check the token validation on startup so you can have a nice user experience.
What I don't understand about your question is de caching thing though.
In addition to #Jesus answer, you can think about implementing a refresh token system: https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/
In the hotel-example, your hotel-card (access-token) would be invalid after time X, but at the reception you can use your passport (refresh-token) to get a new hotel card again.
You could store the refresh token in the database with additional data about the device the user is using, allowing him to disable the device in case it gets stolen.
Example:
first correct client login: Create a refresh token which is valid forever (until it gets deleted or invalidated)
store refresh token in database
return access token (JWT) with expiration time to client ( this token gets not stored in database)
for the next request, the client sends the access token
Now Check if the access token is expired:
5.1 Access Token not expired, all okay
5.2 Access Token expired, check if there is a refresh token in database
5.2.1 Refresh Token is in database, return new Access Token
5.2.2 No Refresh Token in database, return 401 / logout, User has to login again
Hope this helps.
You need to persist the JWT on the client so that it’s available across page loads, the most secure strategy is an HTTPS-only cookie. This will send the JWT to your server on every request and the server can check the validity of the token and reject it if it's expired. How you handle the expiration is dependent on the type of web app you have.
For a single-page application (e.g. Angular.js apps) you would want to structure the application so that it makes an initial request of the server before it bootstraps the rest of the application. If the server sees that the JWT in this request is expired it would issue a 401 response. You application would respond to this response by rendering a login form. Otherwise it would continue with the assumption that the JWT is valid and can be used to access the required resources. If, at any time, the app sees a 401 it should bring the user back to the login form.
For traditional web apps that render their pages on the server: for any request that has an expired JWT (as read from the cookie) the server should issue a 302 redirect to a login form.
I think what you are asking is how to invalidate a JWT server side for long expiry tokens (e.g. "remember me" functionality)?
I ran into this issue myself recently and ended up using a unique user secret to invalidate the token, when the user attempts to validate a token that was produced with an old secret it will fail. The username can be found in the decoded JWT pre verification.
You could probably even use the users password salt for this, that way any current JWT's would be invalidated when a user changes their password (assuming you also change the salt at the same time), this may be problematic though as the password hash and JWT's would become tightly coupled
I can think of one way, but it is not really defined the standard.
What about adding another kind of expiration date with different lifespan to the claims? With two claims, we can treat the shorter one of it as the resource access expiration date, and the longer one as the refresh expiration date, e.g.
{
"iat": /* current time */,
"bbf": /* current time + 1 hour -- expired means no resource access */
"exp": /* current time + 1 week -- expired means cannot refresh */
}
(Note: I use bbf for the shorter expiration date. No specific reason, just because it has 3 characters in length.)
So with "remember me" checked, when the user reconnects, he can use the same token to request for a new one, but not to access the resource. With this, all relevant data is contained within the token -- no extra token required.
And lastly, when "remember me" not checked, just use the same lifespan for bbf and exp.
I'm guessing Yes, but I'm not sure.
Both Authenticated Sessions and Anonymous Sessions would reference the stored sessions via the cookie.
########### edit: Clarify
It seems that sessions require some way of referencing for the stored session data.
This reference could be stored in a cookie OR added as a parameter in the URL.
I know this is taking you too literally, but it seemed appropriate to point out that HTTP is stateless and therefore does not have sessions. In order to maintain state, either the browser or the server have to persist the state information between requests. Traditionally, the server maintains the state, and by convention this is called a session, but it has nothing to do with HTTP as it is a workaround. Also, a session usually has a very specific connotation to it - namely that it is an individual visit to the site that will expire when it is no longer being used (some period of inactivity). It will also be different for the same user using different computers or browsers.
In order to achieve a server session, the server will generally set aside some information in memory or database to keep track of state and use a piece of identifying information to associate http requests with that state. This is usually a token. The browser needs to include information identifying the session with each http request. It doesn't matter how this happens, as long as the server and browser agree. It is most often a cookie, or url parameter as fallback, but as long as you set up the code right it could also be part of the url itself, part of a POST body, or even a non-standard http header.
The alternative that is becoming more and more popular is to maintain state in the browser and use purely ajax calls to the server. In this scenario, the server does not have to maintain any concept of session, and will simply return the data that is requested in a completely user-agnostic way. Some authentication may still be needed if the data is private, but a session token is not, and no state is kept on the server.
You can pass the session ID around as a query parameter (www.blah.com/index.php?SESSIONID=fADSF124323). But it has to be on every page. PHP has a option to enable this transparently. It is a huge mess. This is why cookies are preferred.
Not necessarily, some sites use a session ID value present in the URL that represents the session and this value gets appended to all links visited by the user.
We have to use it this way at work, since often mobile browsers don't accept cookies and this is the only way to remember a session.
Also there is HTTP-Authentication, not used often anymore today as the browser has to send username and password to the server unencrypted on every request.
HTTP-Auth just puts username and password in the header sent by your browser.
you can pretty much uniquely identify people by their browser plugins, fonts, etc.
https://panopticlick.eff.org/
When you're using SSL/TLS, then you could at least theoretically use the SSL session id to reference some state on the server.