Developers of a mobile application are using the timeout period of OAuth 2.0 tokens to check when the application must re-authenticate with the server.
This conflicts with my understanding of the proper use of OAuth 2.0 tokens, although I am not exactly sure that I am correct.
My understanding:
OAuth is not about authentication but about authorization, e.g. can this device access some resource on a server on behalf of a user. Authentication logically precedes authorization and is about confirming the user is who they say they are.
So a user presents credentials (username and password) and the server authenticates that yes, this user is Bob.
The application Bob has logged into wants access to some resources on the server Bob has been authenticated to - say data from an API. So the application requests an OAuth token and it is granted, and one of its attributes is how long it exists. The application and the server exchange keys, and the data between the application and server is encrypted using the key.
An intruder reading the plaintext communication will not be able to decode it without the key. However, if an intruder is able to get the key they will be able to.
This is where the OAuth token end of life comes in. We don't want to use the same OAuth token (key) forever, because if an intruder was able to get that token they can decript our communication forever. If however, we refresh tokens every x hours, then they could decrepit the information only for x hours (let's say 2 hours).
I don't think the OAuth token expiration time should be connected with how long the user remains authenticated. That is simply up to the developers. In our case, if the user has some device security (a passcode for example), then we can let them remain authenticated for a long time (months for example). If they do not have device security then I want to force them to re-authenticate after a reasonable amount of time of inactivity, maybe 24 hours.
Is this correct or not, and if not, what parts.
Thanks in advance.
Bryan
Your understanding on OAuth 2.0 is correct. In very abstract manner, the protocol define a way to obtain tokens, which can be used by a client to communicate against a protected endpoint.
RFC6749 mandate the usage of TLS when communicating with authorization server (the token obtaining) as well as when using it against an API/protected endpoint (Bearer token usage as defined in RFC6750). This protects token from in-transit attacks.
The OAuth access token is recommended to have a short life time. This is to avoid token stealing as well as token misusing that can be done by client. You can read more about best practices from RFC6819. Access token lifetime specifics can be read from here.
Now about selecting the correct life time. As you already figured out, using a refresh token is the desired approach to renew access tokens instead of having a long lasting access tokens. For example, a refresh token can be valid for few days while access token valid only for few hours.
But be mindful about the following,
+ Whether your application can obtain and secure a refresh token
For example, SPA cannot obtain a refresh token as it cannot store it for extended time. In such case you need to look for alternative mechanisms to renew the access token.
+ Is access token used against external domain
Using access token toward an external API increase the threat vector. For example, if you have a closed system (client and backend in one domain) then you may think of increasing access token life time. But not for an extended period like 24hours.!
+ Single sign on (SSO)
Instead of using long lasting access tokens, you can get the help of authorization server to maintain an SSO behavior on top of browser. This is similar to "remember me" you observe in modern login dialogs. Once logged in, browser maintain a cookie which lasts for some time (ex:- A week). The next time you use OAuth token obtaining flow, your authorisations server detect this logged in state, hence skipping login dialog. Of course, such approach must be decided on exact security/policy requirements.
In conclusion, use access tokens with reduced life time.Using refresh token is the desired approach for token renewal. But depending on the situation, you can choose alternatives as well.
Related
If I have an app and an api. If the app logs in through authorization server and sends the authorization: Bearer xxx header with each request, the api can verify the token locally.
When the user logs out (through the auth server), but the token has not yet expired if someone retrieves this token they will be able to make requests (if the authentication of the token is done locally on the server), is that correct? If thats the case, why is such a logout flow considered secure?
Edit: Clarifying the main question: why PKCE flow is considered secure if when a user logs out their access token is still valid (given we do local token verification)
BEHAVIOUR OVERVIEW
With OAuth there is a greater separation of concerns than in older standalone web apps:
You log into UIs
This is externalised to an Authorization Server
An access token is issued with a fixed / short lifetime
Access tokens are used as API message credentials
The access token can potentially be sent to other components and used from there
When you logout:
You remove tokens from your app
You redirect to tell the Authorization Server the user is no longer logged into any UI
This doesn't invalidate access tokens
TOKEN STORAGE
Tokens should be stored in private memory or protected storage so that attackers cannot access them easily. Your app then removes tokens as part of the logout process so that they are no longer available for attackers to try to access.
THREATS
The OAuth Threat Model has a section on stolen tokens, where it recommends the above storage and to keep tokens short lived. The most common industry default for an access token is 60 minutes.
The main risk of a malicious party stealing a token is via cross site scripting. XSS risks are not related to logout. Security testing should be performed regularly to ensure that XSS risks are mitigated.
BALANCE BETWEEN SECURITY AND PERFORMANCE
It may be possible for the UI to tell the Authorization Server that a token is revoked. However, the API would then need to call the Authorization Server on every API request to check for token revocation. This would lead to poor performance.
API ARCHITECTURE
I always aim to use Claims Caching and introspection in OAuth secured APIs, since it gives the actual API best control, along with good extensibility and performance.
With this in place, if you really wanted to make access tokens non usable after logout, without ruining performance, your UI could perform these actions as part of the logout process:
Revoke the access token at the Authorization Server (if supported)
Call APIs to ask them to remove cached claims for the access token
Okta /introspect can tell you if active is true or false, you could check that on every request if you are not slamming the API https://developer.okta.com/docs/reference/api/oidc/#introspect
It's hard to get access to the token, that's probably a good reason why it's not per definition insecure.
However, providing a logout option is a good idea. OAuth2 has a 'revoke' feature to make sure that tokens are revoked:
https://www.rfc-editor.org/rfc/rfc7009
Not every server supports this.
I have been using JWT to authenticate the users for the HTTP endpoints in my ASP.NET Core 2.1 API project. I have configured the authentication service and everything is going on well.
while generating the token, I usually set the expiry to 24 hours. My problem is, what if the user is blocked by the admin after issuing the token. Now that the token is issued the authentication middleware will simply authenticate the request.
So, I thought I need to intercept every request to make a backend call to know whether the user is blocked or not. I can do this at every endpoint level, but it is not so efficient I think.
What are the optimal solutions for this issue, which is quite common? Are there better ways to solve it than what I thought?
When you choose to use a JWT then accept the nature of the JWT. This means that the only way to have 'real-time' information is to expire the token when the information becomes obsolete. Set the lifetime of the access token to a small window, like less than five minutes. This way you know the information is always valid and you don't have to change anything about the current handling. This is 'almost real-time', as the changes become effective within five minutes.
The advantage of a short lifetime is that this also increases the security of your website. When the token is compromised, it can only be used for a short time.
You'll have to add support for a refresh token, because you don't want the user to login every five minutes. So when the access token expires use a refresh token to request a new access token. This will only work for apps that can keep a secret. Because the refresh token is very powerful and you don't want it to fall into the wrong hands. You can use one-time only refresh tokens to limit the risks and add strategies to detect different behaviour. For more details read my answer here.
You can also choose to remove authorization claims from the JWT and move authorization to your middleware, where you can real-time check the permissions of the user. In that case the JWT only includes the user claims that identify and model the user. Claims that are not likely to change very often. As a result the access token doesn't have to be short-lived, but for security reasons I think this is still advisable.
The minimal requirement is a sub or userid claim. This is enough to identify the user and grant the user access to the website.
I think the Policy Server is a good example of a possible middleware authorization implementation. Here the middleware reads permissions from a json file and adds permissions as claims to the identity. Where policies decide what the user is allowed to do. Also implement resource-based authorization.
An alternative is to use reference tokens, as implemented by IdentityServer. IdentityServer stores the contents of the token in a data store and will only issue a unique identifier for this token back to the client. The API receiving this reference must then open a back-channel communication to IdentityServer to validate the token.
The advantage here is that you can revoke the reference token at any time, using the revocation endpoint.
I'm working on a cloud service authentication system and I'm not entirely sure what the optimal way to handle authenticating requests is. We're planning to run our image server as a separate process from our API server so that we can scale them independently of each other. Handling request authentication with API keys is fairly simple, because we can just have the image server store its own API key and check that requests provide it in a header (over HTTPS obviously), same with the API server. For users though it gets more complex.
Right now we have it setup so that the API server will handle generating a session token and storing users in its database, however what we'd like to do is use 3 servers:
authentication server
API server
image server
and have the image and API servers authenticate requests against the authentication server. How exactly should this be done though? It seems like a bad idea performance-wise to hit the authentication server for every request that the API and image servers make. Can/should a token be verified from a different server than it was created on?
So for example: can/should I pass the token received from the authentication server to the image server, verify that the token came from "my.auth.server" and check that the user ID is the right one? Would JWTs be a good type of token for this?
Here's an alternative approach.
Your authentication issues a JWT token that is signed using a secret that is also available in your API and server images. The reason they need to be there too is that you will need to verify the tokens received to make sure you created them. The nice thing about JWTs is that their payload can hold claims as to what the user is authorised to access should different users have different access control levels.
That architecture renders authentication stateless: No need to store any tokens in a database unless you would like to handle token blacklisting (think banning users). Being stateless is crucial if you ever need to scale. That also frees up your API and image servers from having to call the authentication server at all as all the information they need for both authentication and authorisation are in the issued token.
Flow (no refresh tokens):
User authenticates with the authentication server (eg: POST /auth/login) and receives a JWT token generated and signed by the auth server.
User uses that token to talk to your API and image servers and assuming user is authorised), gets and posts the necessary resources.
There are a couple of issues here. Namely, that auth token in the wrong hands provides unlimited access to a malicious user to pretend they are the affected user and call your APIs indefinitely. To handle that, tokens have an expiry date and clients are forced to request new tokens whenever expiry happens. That expiry is part of the token's payload. But if tokens are short-lived, do we require users to authenticate with their usernames and password every time? No. We do not want to ask a user for their password every 30min to an hour, and we do not want to persist that password anywhere in the client. To get around that issue, we introduce the concept of refresh tokens. They are longer lived tokens that serve one purpose: act as a user's password, authenticate them to get a new token. Downside is that with this architecture your authentication server needs to persist these refresh token in a database to make them revokable before they expire (think "revoked" column in tokens table).
New flow (with refresh tokens):
User authenticates with the authentication server (eg: POST /auth/login) and receives a JWT token generated and signed by the auth server, alongside a long lived (eg: 6 months) refresh token that they store securely
Whenever the user needs to make an API request, the token's expiry is checked. Assuming it has not yet expired, user uses that token to talk to your API and image servers and assuming user is authorised), gets and posts the necessary resources.
If the token has indeed expired, there is a need to refresh your token, user calls authentication server (EG: POST / auth/token) and passes the securely stored refresh token. Response is a new access token issued.
Use that new token to talk to your API image servers.
OPTIONAL (banning users)
How do we ban users? Using that model there is no easy way to do so. Enhancement: Every persisted refresh token includes a blacklisted field and only issue new tokens if the refresh token isn't black listed.
Things to consider:
You may want to rotate refresh token. To do so, blacklist the refresh token each time your user needs a new access token. That way refresh tokens can only be used once. Downside you will end up with a lot more refresh tokens but that can easily be solved with a job that clears blacklisted refresh tokens (eg: once a day)
You may want to consider setting a maximum number of allowed refresh tokens issued per user (say 10 or 20) as you issue a new one every time they login (with username and password). This number depends on your flow, how many clients a user may use (web, mobile, etc) and other factors.
You can store some additional metadata (ip, geolocation, device, browser cookie, etc.) alongside refresh tokens. That way, you can be smart about when to reject malicious usages of refresh tokens in case it's compromised.
Common Q: Why store all refresh tokens, and not just revoked ones? You could do that. Ask yourself the following: Will I, at any point, need to have a functionality where I can dynamically revoke valid refresh tokens, based on some arbitrary, regulatory, legal, integrity, security etc. criteria? If so, the least you will need is a list of all issued tokens, plus any data required to implement the criterion logic. Example: Due to regulation, I need to ban all EU users equates to a delete from refresh_tokens were user_ip in <... eu logic ...>
one of the best ways to use is a JWT Token , you can generate and share it between all your servers and validate it on the server side .
https://jwt.io
also I think the best architecture to use in this case is the micro service architecture
For getting access token in twitter api you firstly should get request token to make it possible grant access to user's account. I've found that access token does not expire unless it was revoked by user. What about request tokens? Do they expire? How long are they valid?
Ok, I've found the answer on OAuth specification
http://oauth.net/core/1.0/#anchor9
Used by the Consumer to ask the User to authorize access to the Protected Resources. The User-authorized Request Token is exchanged for an Access Token, MUST only be used once, and MUST NOT be used for any other purpose. It is RECOMMENDED that Request Tokens have a limited lifetime.
Here is also useful diagram of the oauth process (it took me long time to learn the flow)
So the answer is - very short.
PS: the reason why I was asking question is just to simplify the whole process by getting request tokens once and use it several times for different users.
Your access token will be invalid if a user explicitly rejects your application from their settings or if a Twitter admin suspends your application. If your application is suspended there will be a note on your application page saying that it has been suspended.
You should plan that a user’s access token may become invalid at any time and you will need to re-authorize for that user in the case that it does. Ensuring you handle this situation gracefully is imperative for a quality user experience.
I have a couple security questions on the OAuth 2.0 User Credential Grant type and possible security attacks. So from what I understand so far, when I exchange my users username password client ID and client secret for an access token over HTTPS that is completely safe. Now say for an example if I have a first party mobile application for a service that is doing the user authentication and I keep the access token on the device.
If the access token is compromised some how the compromised access token can be used to make subsequent requests to say for example the API service. Is there any way to prevent this other than just not getting the access token out there?
If your doing all API requests over HTTPS I shouldn't have to be worried what so ever about the access token being compromised over the wire or have to worry about any replay attacks?
So basically my concerns about possible security flaws with this specific type of grant. I'm pretty sure if the access token doesn't get compromised and all traffic is over SSL it should be fine.
I'd love to hear someone's expert opinion not the biggest OAuth person.
If the access token is compromised, the app that now has it CAN misuse it. Since access tokens are short lived, and are mapped to certain permissions only - the damage would be limited to say 10 minutes access to a single resource! (tokens are generated for apps that are registered for a scope, the scopes are mapped to permissions.)
If you are working on a first party app, why do you want to store the token on device? You can think of using the authorization code flow and not the implicit grant flow. That way the access token is always with the server and not on the device locally.