Just reading the docs, they seem very similar to me so I can't really discern why to use one over the other. Although identity token seems better since it has custom attributes on it from the user pool (eg: custom:blah and the default ones like name and email).
Right now, I am working with an app that passes the access token back down to the browser so it can use it for making ajax REST calls (there is an auth filter that expects this access token and validates it). Could I just switch out the access token with the id token? The current validation logic is to just get the sub field (the uuid) from the access token, but this sub field is also present in the identity token (as well as practically every other attribute except the aud which I don't need). I just want to make sure I am understanding this right as it is confusing to me why both tokens exist and seem so similar.
The id_token is for your application to process, so you can get all the personal details for your user, like their name, age, email address etc. Generally speaking you shouldn't send this token anywhere else as it contains sensitive user data.
The access_token is used to call other 'external' services (and by external I include other AWS services - these are often called over http). It provides service access authorisation for your user without having to include their personal details.
On the face of it this appears slightly confusing as you can actually use the id_token to access services in the same way as the access_token. However, good practise is to use the access_token in this circumstance and if backend services need user data, they should look it up themselves in Cognito.
EDIT: If you need to authenticate an api call based on claims in the identity token, there are circumstances when this is perfectly valid. But be aware of what details are in the identity token, and whether those claims are suitable to send to the particular API. If you don't need to use any claims from the id_token, use the access_token as this reduces the amount of potentially sensitive data you are sending.
The thing that wasn't obvious from documentation for me about the difference:
If you are using pretoken trigger function and want to add additional information to the claims with claimsToAddOrOverride , you need to use an id token because this information doesn't exist in the access token.
For ex:
event.response = {
claimsOverrideDetails: {
claimsToAddOrOverride: {
'userProfileID': id,
}
},
}
I've expected it in the AppSync resolver with lambda function as source
Speaking about AWS User Pool tokens:
Identity token is used to authenticate users to your resource servers or server applications. For example, if you use Cognito as authorizer in AWS API Gateway you need to use Identity token to call API.
The purpose of the access token is to authorize API operations in the context of the user in the user pool. For example, you can use the access token to grant your user access to add, change, or delete user attributes.
The header for the access token has the same structure as the ID token. However, the key ID (kid) is different because different keys are used to sign ID tokens and access tokens.
I am using Spring Security OAuth2 and JWT tokens. My question is: How can I revoke a JWT token?
As mentioned here
http://projects.spring.io/spring-security-oauth/docs/oauth2.html, revocation is done by refresh token. But it does not seem to work.
In general the easiest answer would be to say that you cannot revoke a JWT token, but that's simply not true. The honest answer is that the cost of supporting JWT revocation is sufficiently big for not being worth most of the times or plainly reconsider an alternative to JWT.
Having said that, in some scenarios you might need both JWT and immediate token revocation so lets go through what it would take, but first we'll cover some concepts.
JWT (Learn JSON Web Tokens) just specifies a token format, this revocation problem would also apply to any format used in what's usually known as a self-contained or by-value token. I like the latter terminology, because it makes a good contrast with by-reference tokens.
by-value token - associated information, including token lifetime, is contained in the token itself and the information can be verified as originating from a trusted source (digital signatures to the rescue)
by-reference token - associated information is kept on server-side storage that is then obtained using the token value as the key; being server-side storage the associated information is implicitly trusted
Before the JWT Big Bang we already dealt with tokens in our authentication systems; it was common for an application to create a session identifier upon user login that would then be used so that the user did not had to repeat the login process each time. These session identifiers were used as key indexes for server-side storage and if this sounds similar to something you recently read, you're right, this indeed classifies as a by-reference token.
Using the same analogy, understanding revocation for by-reference tokens is trivial; we just delete the server-side storage mapped to that key and the next time the key is provided it will be invalid.
For by-value tokens we just need to implement the opposite. When you request the revocation of the token you store something that allows you to uniquely identify that token so that next time you receive it you can additionally check if it was revoked. If you're already thinking that something like this will not scale, have in mind that you only need to store the data until the time the token would expire and in most cases you could probably just store an hash of the token so it would always be something of a known size.
As a last note and to center this on OAuth 2.0, the revocation of by-value access tokens is currently not standardized. Nonetheless, the OAuth 2.0 Token revocation specifically states that it can still be achieved as long as both the authorization server and resource server agree to a custom way of handling this:
In the former case (self-contained tokens), some (currently non-standardized) backend interaction between the authorization server and the resource server may be used when immediate access token revocation is desired.
If you control both the authorization server and resource server this is very easy to achieve. On the other hand if you delegate the authorization server role to a cloud provider like Auth0 or a third-party component like Spring OAuth 2.0 you most likely need to approach things differently as you'll probably only get what's already standardized.
An interesting reference
This article explain a another way to do that: Blacklist JWT
It contains some interesting pratices and pattern followed by RFC7523
The JWT cann't be revoked.
But here is the a alternative solution called as JWT old for new exchange schema.
Because we can’t invalidate the issued token before expire time, we always use short-time token, such as 30 minute.
When the token expired, we use the old token exchange a new token. The critical point is one old token can exchange one new token only.
In center auth server, we maintain a table like this:
table auth_tokens(
user_id,
jwt_hash,
expire
)
user_id contained in JWT string.
jwt_hash is a hash value of whole JWT string,Such as SHA256.
expire field is optional.
The following is work flow:
User request the login API with username and password, the auth server issue one token, and register the token ( add one row in the table. )
When the token expired, user request the exchange API with the old token. Firstly the auth server validate the old token as normal except expire checking, then create the token hash value, then lookup above table by user id:
If found record and user_id and jwt_hash is match, then issue new token and update the table.
If found record, but user_id and jwt_hash is not match , it means someone has use the token exchanged new token before. The token be hacked, delete records by user_id and response with alert information.
if not found record, user need login again or only input password.
when use changed the password or login out, delete record by user id.
To use token continuously ,both legal user and hacker need exchange new token continuously, but only one can succeed, when one fails, both need to login again at next exchange time.
So if hacker got the token, it can be used for a short time, but can't exchange for a new one if a legal user exchanged new one next time, because the token validity period is short. It is more secure this way.
If there is no hacker, normal user also need exchange new token periodically ,such as every 30 minutes, this is just like login automatically. The extra load is not high and we can adjust expire time for our application.
source: http://www.jianshu.com/p/b11accc40ba7
This doesn't exactly answer you question in regards to the Spring framework, but here's an article that talks about why if you need the ability to revoke JWT's, you might not want to go with JWT's in the first place, and instead use regular, opaque Bearer tokens.
https://www.dinochiesa.net/?p=1388
One way to revoke a JWT is by leveraging a distributed event system that notifies services when refresh tokens have been revoked. The identity provider broadcasts an event when a refresh token is revoked and other backends/services listen for the event. When an event is received the backends/services update a local cache that maintains a set of users whose refresh tokens have been revoked.
This cache is then checked whenever a JWT is verified to determine if the JWT should be revoked or not. This is all based on the duration of JWTs and expiration instant of individual JWTs.
This article, Revoking JWTs, illustrates this concept and has a sample app on Github.
For Googlers:
If you implement pure stateless authentication there is no way to revoke the token as the token itself is the sole source of truth
If you save a list of revoked token IDs on the server and check every request against the list, then it is essentially a variant of stateful authentication
OAuth2 providers like Cognito provides a way to "sign out" a user, however, it only really revokes refresh token, which is usually long-lived and could be used multiple times to generate new access tokens thus has to be revoked; the existing access tokens are still valid until they expire
What about storing the JWT token and referencing it to the user in the database? By extending the Guards/Security Systems in your backend application with an additional DB join after performing the JWT comparison, you would be able to practically 'revoke' it by removing or soft-deleting it from the DB.
In general, the answer about tokens by reference vs. tokens by value has nailed it. For those that stumble upon this space in future.
How to implement revocation on RS side:
TL;DR:
Take a cache or db that is visible to all your backend service instances that are verifying tokens. When a new token arrives for revocation, if it's a valid one, (i.e. verifies against your jwt verification algo), take the exp and jti claims, and save jti to cache until exp is reached. Then expire jti in cache once unixNow becomes > exp.
Then on authorization on other endpoints, you check everytime if a given jti is matching something in this cache, and if yes, you error with 403 saying token revoked. Once it expires, regular Token Expired error kicks in from your verification algo.
P.S. By saving only jti in cache, you make this data useless to anyone since it's just a unique token identifier.
The best solution for JWT revocation, is short exp window, refresh and keeping issued JWT tokens in a shared nearline cache. With Redis for example, this is particularly easy as you can set the cache key as the token itself (or a hash of the token), and specify expiry so that the tokens get automatically evicted.
I found one way of resolving the issue, How to expire already generated existing JWT token using Java?
In this case, we need to use any DB or in-memory where,
Step 1: As soon as the token is generated for the first time for a user, store it in a db with the token and it's "issuedAt()" time.
I stored it in DB in this JSON format,
Ex: {"username" : "username",
"token" : "token",
"issuedAt" : "issuedAt" }
Step 2: Once you get a web service request for the same user with a token to validate, fetch "issuedAt()" timestamp from the token and compare it with stored(DB/in-memory) issued timestamp.
Step 3: If stored issued timestamp is new (using after()/before() method) then return that the token is invalid (in this case we are not actually expiring the token but we are stop giving access on that token).
This is how I resolved the issue.
I created "test-App" application in API Manager WSO2 with the grant types of "refresh-token" "SAML2", "PASSWORD" "Client Credentials" and "JWT"
I also Created a "test"
To use the webservices behind API manager, First, I should call https://localhost:9443/oauth2/token) to get a access-token
Unfortunately, if I call the link again, instead of receiving the same access-token, the system will generate a new access-token and the previous access-token would be expired. ( I think this link is more like refresh token rather than get the access token).
So, How can I Separate getting available access-token and Refresh-token link in WSO2 API Manager ?
In the latest versions of API Manager you have JWT tokens. When you request a new token it always generates a new token. But it doesn’t revoke the previous access token.
In the earlier versions of APIM, opaque tokens were supported and it has a different behavior. When you request a token, if it is not expired you get the same token.
Please read more about refresh grant here https://apim.docs.wso2.com/en/latest/design/api-security/oauth2/grant-types/refresh-token-grant/
If you have not done any other configuration changes, invoking https://localhost:9443/oauth2/token URL will always generate a new JWT token without expiring the earlier one. However, the token validity can be changed in the Dev Portal while generating the access token.
I'm using the php-jwt package for my Restful API to authneticate users.
I am successfully authenticating Users and returning a token. However it seems that there is not a standard method to issue a refresh token. Although I understand the principle and the flow I'm not sure if there is a standard for the issuing of the refresh token?
If I unerstand correctly the flow is as follows:
App requests access
API checks for a valid User and issues a token which is to include a refresh token
refresh token is sent along with a request to renew, it is verified and if valid another token is issued?
But my question is how to issue the initial refesh token. Is this simply encoded in the token itself along with other data that I return such as username and email for example?
Thanks in advance. A.
I'm currently doing a bit of research of my own on JWTs. I believe you can give the client 2 tokens after auth: an access token and a refresh token. The refresh token can also be a JWT itself. What goes in it is up to you but I think what's important is that it is a valid/not expired token when used. If you can successfully validate it, then you can issue a new access token.
The Twitter OAuth 1.0a flow requires authenticated request token to be exchanged with access token at consumer or client side after user has authenticated.
The problem that I'm facing is that generating access token needs authenticated request token, request token secret and verifier but the response from the oauth/authentication api doesn't have request token secret. So how do I temporarily save request token secret from oauth/request_token api call so that I can use it in oauth/access_token api call.
I found some solutions from my explorations like Running a Cache server (Memcached, Redis) or using django session feature. But they all seem to be overkill for this task.
I hope to find a simpler solution.
I'm sure you long ago figured this out, but just for future goolers: I decided to a go a more low tech route and create an OAuth token class which includes fields for the fetched and access token. Basically I take the fetched token, store it, then recall it when accessing (as it's in a different view) and then save the access token. Once (if) that's successful than I delete the fetched token.
There's likely a more glamorous way to do this, but if you're clever with your naming convention you can easily keep them straight (i.e. add a CharField for provider and just save the fetched token as twitter_fetched, and the access token as just twitter).
This has the added benefit of allowing you to create an OAuth1 or OAuth1Session from the stored access token.