I just started integration of OpenID in my website. All the examples I saw store the claimed IDs in cookies. How is it safe?
For example, myopenid.com returns a claimed ID that is {username}.myopenid.com
So if a hacker knows your claimed ID, he can easily hack your account.
Of course you encipher/md5 the ID before putting it into the cookies and using for authentication, but it's like storing a username without password!
Update
Now that I thought more about it, I realized, that you need to be logged in the OpenID provider, so even if the hacker gets the username, he still needs the provider's password to log in. Am I correct?
Update 2
No, update 1 is not correct :) My site cannot check whether the user is successfully logged in or not. All I receive is the claimed ID, and I just have to trust that the user is authenticated. That's really confusing...
Knowing the user's claimed identity isn't enough to authenticate.
Indeed, the user would have to be logged in to his provider, in order to authenticate with your website using that identity.
As for "trusting that the user is authenticated" -- no, you don't trust. As a final part of OpenID authentication you're supposed to verify that the authentication message comes from the provider. There are various security measures in place to ensure that the message is authentic, unaltered, etc.
If you do that, you're sure that your user is properly authenticated by the provider.
Now, since you don't want to do it every time your user makes a request, you store the session information in a cookie. However, you don't store only the claimed identifier (if you decide to store it at all), but a session id -- a pseudorandom number generated at the moment your user logs in. Since it's pseudorandom, no one can guess it, and therefore, knowledge of a claimed identifier itself doesn't mean anything.
If that answers your question, read about session management in your favorite language/framework, as it will tell you how to easily implement such mechanism, and how it works.
In summary: think of OpenID as a replacement for a password verification. You don't need to (and shouldn't) store logins and passwords in cookies, and you don't have to store claimed identifiers. Similarly, you don't verify that the login and password matches every time, but remember that the user is authenticated in a session.
Related
I am using JWT for authentication. However I do not want the user to be logged in from multiple devices. How do I ensure this?
Right now - All I can think of is to store the JWT into DB and then check if it exists . And if it exists, what was the time it was generated at. If too much time - we go and regenerate the token and pass on back to the 2nd device.
That's pretty much your only option, the JWT is pretty stateless on purpose. Similar to how you can't really do a server side logout without similar technique
As jfriend points out, storing the JWT alone is insufficient. What you need to do with it is ensure that the next time a user requests login, that they don't already have an unexpired JWT issued to them.
Going through the flow for completeness:
Case 1: User isn't logged in anywhere. In this case, JWT is issued and stored. Possibly in the user record for easy retrieval.
Case 2: User tries to log in on another device. Whether you make them explicitly log out of the first device or do it for them, you have to now send that stored token into a list of revoked tokens. Your token validation logic will have to take that list into account when determining if a token is valid or not.
/* Further clarification */
I feel like a bit more detail might be useful for folks, so I'm going to go into implementation a bit.
** Unauthenticated requests **
This shouldn't change, but it's worth mentioning that I'm assuming you have routes that require authentication, and requests to those routes which do not include an active and valid JWT get rejected with a 401 (and probably provided the URL to the login url).
Login
Login logic always includes a user lookup, so as described above, the flow in this application should include that lookup, but before logging the user in the application you will check to see if there's already an assigned token to the user which has not expired.
If there is not a token already assigned to the user, then check credentials however you normally would, generate a JWT (with an exp heading to indicate expiration time in the payload), save that token back in the user document/record for future reference.
If there is an assigned token which is also unexpired, then you either have to log the user out of the other device (more on that in a second), and log them in to the current device, or else you have to reject the login attempt and keep the person logged out of the new device. I think the former approach is more user friendly, but it depends on the needs of your application.
Logout
With JWT, the only way to guarantee a user is unable to use an issued token is to either include an expiration time (exp) in the payload, and use a verifier that checks that, or to know on the server which tokens are no longer valid and check against them. The most robust solutions do both.
So, assuming you're handling the expiration already the explicit logout feature would be handled by creating a revoked tokens list somewhere. If you're using MongoDB, for example, you'd create a collection to store those. You'd ideally also set a TTL on each one that is set to some point after the expiration date, so that Mongo will evict tokens that are otherwise expired anyway, to save yourself time and space.
If you're doing the auto-logout on a new login request, you'll hit this logic to place the old token into the revoked tokens list when you save the new token in the user's document.
The logout route should also be reachable by authenticated users, to explicitly logout if they want, regardless of whether you do the auto logout or not.
Authenticated Requests
By this point you should be reasonably certain that users can only login on one device. However, you also need to make sure that they aren't trying to make a request with a revoked token.
Your generalized route security middleware would then need to also check the revoked token list to see if the token offered by the client is on said list after checking to make sure it's not expired (since the expiry can be checked upon validation, saving a round-trip to the DB.
I totally agree with #Prateek Narendra.
once user is logged in store it's token in DB (i stored it in activeJWT field) then on further login check if activeJWT is null or not.
If yes then allow login else not.
At logout time u need to make activeJWT field null.
you can decode the current token for that.
Note: I am not an expert in auth.
I think you should save the last_login date time in DB.
Set JWT expire to 7 days. Renew JWT token for every request (for example user request /user this endpoint here sends new JWT token every time.)
On logout set last_login to null
When someone tries to log in
check the last_login field if it is null or last_login date-time is older then 7 day then procced otherwise
display a message to Logout first.
I'm building a basic website where a logged in user makes requests to a server. What are some good practices for the server to verify that the user is who he says he is? Right now I create a session key every time the user logs in which is then stored in the DB. the session key is the hash of the users username concatenated with the current time. Every time the user makes a request he sends along the session key to be verified. Are there any security flaws with this method?
Yes, this isn't real security. It is know as Security by Obscurity.
If an attacker wants to hijack a session, all they would have to do is hash the username along with the time and set it as their cookie value. Of course this would have to correspond with a valid user session being logged on at that time, but they could easily script this.
For example, if they wanted to log on as bob#example.com the could simply generate the hash of bob#example.com:00:00:00, bob#example.com:00:00:01, bob#example.com:00:00:02, etc, etc, until they find a session value that allows them to access privileged pages.
When a user forgets his password, you shouldn't send it by email. In his Pluralsight course "Hack Yourself First: How to go on the Cyber-Offense", Troy Hunt states that "there is no implicit transport-layer security on SMTP". This answer on Information Security Stack Exchange confirms that it's a bad idea to send or store passwords in the clear (including by email).
The proper way to reset a password, it seems, is to not reset it immediately. Instead, send the user a time-limited activation link via email. This requires manual intervention of the user and also does not communicate the password via email at any stage.
The aforementioned Information Security answer describes how one might implement a password-reset mechanism:
Don't RESET user's passwords no matter what - 'reset' passwords are harder for the user to remember, which means he/she MUST either change it OR write it down - say, on a bright yellow Post-It on the edge of his monitor. Instead, just let users pick a new one right away - which is what they want to do anyway.
If a user forgets their password, send them a secure one-time reset link, using a randomly generated reset token stored in the database. The token must be unique and secret, so hash the token in the database and compare it when the link is used.
The definitive guide to form based website authentication describes the implementation similarly:
Always hash the lost password code/token in the database. AGAIN, this code is another example of a Password Equivalent, so it MUST be hashed in case an attacker got his hands on your database. When a lost password code is requested, send the plaintext code to the user's email address, then hash it, save the hash in your database -- and throw away the original. Just like a password or a persistent login token.
But how will the user actually know the new password. Is it reset to some default? Is it changed to a randomly-generated password that needs to be communicated with the user somehow?
In "Hack Yourself First: How to go on the Cyber-Offense", the activation link takes you to a form where you can enter your new password.
That might be okay if you're dealing with a website, where you can go in and interact with the web application and choose your own new password. But with something like the .NET Web API, you're interacting with actions on controllers that are normally supposed to give you data, not a user interface. You can't just give them a link and expect them to do something with it.
Thus, if you're dealing with authentication over Web API, what is an effective and secure way to allow users to reset their passwords and also communicate the new password to them?
The thing to remember in this scenario is that Web API is just that: an API. Even though there might not be a website, there is still a user interface somewhere (an actual website, or a WPF application, or a mobile application - doesn't matter). So the usual secure "forgotten password" functionality can still be implemented.
There is one difference, however. Instead of sending a link, send the token itself. The UI then provides the place to enter the token. The steps to follow are below:
The user wanting to reset his password goes to the appropriate "Forgotten Password" screen in the UI.
The user is prompted for his username.
A token is sent to his associated email address in plaintext. The hashed version is stored in the database together with an expiry of, e.g., one hour from now.
The user enters the token in the next screen.
If the token is valid, the user is taken to a screen in which he can enter a new password (without having to enter the old one - the token already authenticated him).
Sending a plaintext token via email might sound a bit like sending a password via email. However the fact that it expires after a short period of time gives an attacker a very small window of opportunity to use it. Also, the token is one-time, and is discarded upon use.
There are two concepts you're addressing in this question: password reset and the mechanics involved, and the proper way to authenticate a user to a web API. I think it's important to draw a distinction between them and to understand the latter first.
Imagine you have a web application and a protected resource (web API). The web API requires that all callers must be authenticated by some mechanism. One way to allow a user to authenticate to the web API is to present credentials directly to the web API, but this presents many other issues such as the web API needing to store/maintain/access user account info, the security weakness in sending passwords along the wire in this fashion, the broad scope the web API has to act on the user's behalf when it obtains their raw credentials, etc.
You've probably heard of OAuth 2.0, which addresses these problems. A better way of accessing a protected resource (web API) is to add an authorization layer. For example, a web app presents a dialog for entering a user's credentials, which are then sent to an authorization server and validated, which produces an access token. The access token can then be used to authenticate calls to the web API on behalf of the user (or on behalf of an application using client credentials grant). Using this flow, the web API doesn't need to authenticate users directly, it can be much more lightweight, and many other security issues with the other flow are addressed. See the OAuth 2.0 specification for more detail.
Getting back to your example, a better answer is that you manage password reset at a different level. Your web API shouldn't have to know about the user and password at all, let a lone resetting it -- it should just receive a token and validate it. This allows you to play around with your desired password reset method and it won't affect access to any of your downstream resources.
Currently on our web-based apps we don't allow users to save their login information. The login itself is simply a secure cookie with a random hash which points to session information on the back end. There are no issues like HIPAA to be had, we just never implemented saving credentials, because it doesn't seem like a good idea to me.
What are the pros and cons from a security perspective on this? I worry about users getting saved cookies taken, though we do check session against IP address as well. I just don't want to miss anything.
Never 'save' the credentials, always generate a secure token that you will store on the client side and treat it as if it was the user's password (it kind of is, actually).
But first:
High value applications MUST NOT possess remember me functionality.
Medium value applications SHOULD NOT contain remember me functionality. If present, the user MUST opt-in to remember me. The system SHOULD strongly warn users that remember me is insecure particularly on public computers
Low value applications MAY include an opt-in remember me function. There should be a warning to the user that this option is insecure, particularly on public computers.
Always give the user an overview of active sessions once he is logged in and give him the option to terminate certain sessions.
You could use this strategy described here as best practice:
When the user successfully logs in with Remember Me checked, a login cookie is issued in addition to the standard session management cookie.
The login cookie contains the user's username, a series identifier, and a token. The series and token are unguessable random numbers from a suitably large space. All three are stored together in a database table.
When a non-logged-in user visits the site and presents a login cookie, the username, series, and token are looked up in the database.
If the triplet is present, the user is considered authenticated. The used token is removed from the database. A new token is generated, stored in database with the username and the same series identifier, and a new login cookie containing all three is issued to the user.
If the username and series are present but the token does not match, a theft is assumed. The user receives a strongly worded warning and all of the user's remembered sessions are deleted.
If the username and series are not present, the login cookie is ignored.
I want to understand what token-based authentication means. I searched the internet but couldn't find anything understandable.
I think it's well explained here -- quoting just the key sentences of the long article:
The general concept behind a
token-based authentication system is
simple. Allow users to enter their
username and password in order to
obtain a token which allows them to
fetch a specific resource - without
using their username and password.
Once their token has been obtained,
the user can offer the token - which
offers access to a specific resource
for a time period - to the remote
site.
In other words: add one level of indirection for authentication -- instead of having to authenticate with username and password for each protected resource, the user authenticates that way once (within a session of limited duration), obtains a time-limited token in return, and uses that token for further authentication during the session.
Advantages are many -- e.g., the user could pass the token, once they've obtained it, on to some other automated system which they're willing to trust for a limited time and a limited set of resources, but would not be willing to trust with their username and password (i.e., with every resource they're allowed to access, forevermore or at least until they change their password).
If anything is still unclear, please edit your question to clarify WHAT isn't 100% clear to you, and I'm sure we can help you further.
From Auth0.com
Token-Based Authentication, relies on a signed token that is sent to
the server on each request.
What are the benefits of using a token-based approach?
Cross-domain / CORS: cookies + CORS don't play well across different domains. A token-based approach allows you to make AJAX
calls to any server, on any domain because you use an HTTP header
to transmit the user information.
Stateless (a.k.a. Server side scalability): there is no need to keep a session store, the token is a self-contained entity that conveys all the user information. The rest of the state lives in cookies or local storage on the client side.
CDN: you can serve all the assets of your app from a CDN (e.g. javascript, HTML, images, etc.), and your server side is just the API.
Decoupling: you are not tied to any particular authentication scheme. The token might be generated anywhere, hence your API can
be called from anywhere with a single way of authenticating those
calls.
Mobile ready: when you start working on a native platform (iOS, Android, Windows 8, etc.) cookies are not ideal when consuming a
token-based approach simplifies this a lot.
CSRF: since you are not relying on cookies, you don't need to protect against cross site requests (e.g. it would not be possible to
sib your site, generate a POST request and re-use the existing authentication cookie because there will be none).
Performance: we are not presenting any hard perf benchmarks here, but a network roundtrip (e.g. finding a session on database)
is likely to take more time than calculating an HMACSHA256 to
validate a token and parsing its contents.
A token is a piece of data which only Server X could possibly have created, and which contains enough data to identify a particular user.
You might present your login information and ask Server X for a token; and then you might present your token and ask Server X to perform some user-specific action.
Tokens are created using various combinations of various techniques from the field of cryptography as well as with input from the wider field of security research. If you decide to go and create your own token system, you had best be really smart.
A token is a piece of data created by server, and contains information to identify a particular user and token validity. The token will contain the user's information, as well as a special token code that user can pass to the server with every method that supports authentication, instead of passing a username and password directly.
Token-based authentication is a security technique that authenticates the users who attempt to log in to a server, a network, or some other secure system, using a security token provided by the server.
An authentication is successful if a user can prove to a server that he or she is a valid user by passing a security token. The service validates the security token and processes the user request.
After the token is validated by the service, it is used to establish security context for the client, so the service can make authorization decisions or audit activity for successive user requests.
Source (Web Archive)
Token Based (Security / Authentication)
This means that in order for us to prove that we’ve access we first have to receive the token. In a real-life scenario, the token could be an access card to the building, it could be the key to the lock to your house. In order for you to retrieve a key card for your office or the key to your home, you first need to prove who you are and that you in fact do have access to that token. It could be something as simple as showing someone your ID or giving them a secret password. So imagine I need to get access to my office. I go down to the security office, I show them my ID, and they give me this token, which lets me into the building. Now I have unrestricted access to do whatever I want inside the building, as long as I have my token with me.
What’s the benefit of token-based security?
If we think back on the insecure API, what we had to do in that case was that we had to provide our password for everything that we wanted to do.
Imagine that every time we enter a door in our office, we have to give everyone sitting next to the door our password. Now that would be pretty bad because that means that anyone inside our office could take our password and impersonate us, and that’s pretty bad. Instead, what we do is that we retrieve the token, of course together with the password, but we retrieve that from one person. And then we can use this token wherever we want inside the building. Of course, if we lose the token, we have the same problem as if someone else knew our password, but that leads us to things like how do we make sure that if we lose the token, we can revoke the access, and maybe the token shouldn’t live for longer than 24 hours, so the next day that we come to the office, we need to show our ID again. But still, there’s just one person that we show the ID to, and that’s the security guard sitting where we retrieve the tokens.
The question is old and the technology has advanced, here is the current state:
JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for passing claims between parties in web application environment. The tokens are designed to be compact, URL-safe and usable especially in web browser single sign-on (SSO) context.
https://en.wikipedia.org/wiki/JSON_Web_Token
It's just hash which is associated with user in database or some other way. That token can be used to authenticate and then authorize a user access related contents of the application. To retrieve this token on client side login is required. After first time login you need to save retrieved token not any other data like session, session id because here everything is token to access other resources of application.
Token is used to assure the authenticity of the user.
UPDATES:
In current time, We have more advanced token based technology called JWT (Json Web Token). This technology helps to use same token in multiple systems and we call it single sign-on.
Basically JSON Based Token contains information about user details and token expiry details. So that information can be used to further authenticate or reject the request if token is invalid or expired based on details.
When you register for a new website, often you are sent an email to activate your account. That email typically contains a link to click on. Part of that link, contains a token, the server knows about this token and can associate it with your account. The token would usually have an expiry date associated with it, so you may only have an hour to click on the link and activate your account. None of this would be possible with cookies or session variables, since its unknown what device or browser the customer is using to check emails.