What is the SessionSecurityToken SecurityKeys? - token

I want to validate a SessionSecurityToken issued by a STS. By validate, I mean certify that the token is not crafted and verity that the token is issued from the STS.
Conceptually, I know that if the STS encrypt (or sign) the token with it's private key, I could decrypt (or validate signature) with a public key.
From what I understand, the STS I am using (ThinkTecture Identity Server) uses a Symmetric Signing Key to sign to token.
The SessionSecurityToken I received contains a SecurityKeys property. What represent this SecurityKeys? MSDN documentation tells: "Gets the keys associated with this session. This is usually a single key."
Is it the SymmetricKey used by my STS? If so, it means that the symmetric key is not well protected, and if anybody gets this key, he could fake a token.
Is it the token signature? If so, how can I validate the signature (assuming that I have the symmetric key)?
Any other useful information to help me understand the way we validate a SessionSecurityToken?

So first of all - STSes don't issue a session token. They issue (i guess you use WS-Fed) a SAML token. This token is signed with an X.509 certificate.
The relying party then takes the incoming SAML token and turns it into a session token and writes that to a cookie.
So why do you want to validate that? This is done automatically by the SAM.

Related

How do you guarantee safety when validating Keycloak (OIDC) tokens without making requests to the Keycloak API?

There is a lot of information on OAuth, OIDC and Keycloak, but the main thing every tutorial seems to gloss over is offline validation. The only information I found is in the Keycloak docs on RPT introspection:
No. Just like a regular access token issued by a Keycloak server, RPTs also use the JSON web token (JWT) specification as the default format. If you want to validate these tokens without a call to the remote introspection endpoint, you can decode the RPT and query for its validity locally. Once you decode the token, you can also use the permissions within the token to enforce authorization decisions.
If I wanted to verify a user's request with an authorization token, I would make a request to the Keycloak introspection (or userinfo?) API. I'm not completely sure, but I would guess that Keycloak then verifies the info encoded in the JWT with the Keycloak user database.
However, what if I don't want to make a Keycloak request on every API request? This could improve system performance by limiting the amount of HTTP requests. There are mentions of JWT signature validations and reading the scope and user information encoded in the JWT, but I don't see how this guarantees safety. Isn't it possible to just generate any old JWT, encode any information you want and basically spoof an authorization token? How would I check if the user mentioned in the JWT really exists in the Keycloak database?
I think I am missing some crucial part of this technology.
For example, in ASP.NET Core, an API that receives a JWT token will, at startup, download the public signing keys from the token provider, and by default, it will refresh the keys every 24 hours.
So, when the API receives a JWT token, it will do various checks to validate the token, including:
Validating the signature using the provider public signing key
Validate the audience claim (is the token intended for me?)
Validate the expiry date
The API should not need to query anything against the token provider (keycloak) to let the user in.
However, then we have authorization (What the user is allowed to do), which is a different thing, and that all depends on your requirements.
JWT is all about who the user is; if the token is valid, you can trust that information.
With JWT-tokens, your API can work almost offline from the token provider. It can even be 100% disconnected if you copy the public signing key manually into the API.

Where to validate nonce in OAuth 2.0 Implict Flow?

I have the following architecture.
Where:
Client - is a single page JavaScript application.
Authorisation server - is Azure AD.
Resource server - is an Azure App Service using Azure AD authentication.
All communications are secured using HTTPS.
I am using Implicit Flow to access a JWT access token from Azure AD.
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=id_token+token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&scope=openid%20https%3A%2F%2Fgraph.microsoft.com%2Fmail.read
&response_mode=fragment
&state=12345
&nonce=678910
This JWT token is then later passed to the resource server as a Bearer authorization. The same token could be reused multiple times before it expires.
As part of the Authorize request I pass state and a nonce value.
Presently I validate the state on my client in JavaScript using a simple if:
function isValid() {
if (token.state !== expectedState) {
return false;
}
...
}
If I understand correctly the nonce is to prevent replay attacks - which I assume meant against my resource server, but perhaps also against the client.
I am unsure where (or if) I should validate the nonce.
On the server doesnt seem right, the token as a whole is being validated, and the token is meant to be reusable (within its expiry).
On the client, seems to be a better location, but is that any different to validating the state?
I am unsure where (or if) I should validate the nonce.
Of course, you should validate the nonce. Because the nonce is required and it will be returned and contained as a claim in the id_token. When you validate the id_token, you would just validate the nonce claim. Using nonce is to mitigate token replay attacks (someone who want to use token replay attack won't know the nonce, so each token has different nonce to identify the origin of the request).
There is a clear explanation for nonce for AAD v2 endpoint:
#nonce (required)
A value included in the request, generated by the app, that will be
included in the resulting id_token as a claim. The app can then verify
this value to mitigate token replay attacks. The value is typically a
randomized, unique string that can be used to identify the origin of
the request.
So, you can just validate the id_token to validate the nonce.
but is that any different to validating the state?
Yes, the effect of nonce is different from state. First, nonce will be returned in the id_token and you can validate it when you decode and validate the id_token. But state is returned in the response, not in the token. Also, state has different meaning and effect from nonce.
#state (recommended)
A value included in the request that will also be returned in the
token response. It can be a string of any content that you wish. A
randomly generated unique value is typically used for preventing
cross-site request forgery attacks. The state is also used to encode
information about the user's state in the app before the
authentication request occurred, such as the page or view they were
on.
Additional, replay attack is different from cross-site request forgery attacks. You can refer for more details about these two attacks. Then, you will understand why nonce is in the token and state is in the response.
Whether validate the nonce (token) at client
For id_token, yes, it just should be validate from the client.
For SPA with implicit flow, we can use ADAL.js to validate nonce, the id_token which contains the nonce claim to mitigate token replay attacks.
Hope this helps!
As a general point I'd recommend using the excellent oidc-client certified library to do this for you
It is tricky with Azure AD but I have a documented sample that works and that we used at my last company:
http://authguidance.com/2017/11/30/azure-active-directory-setup/
Happy to answer any questions if it helps ..

Verification of ID tokens on client side

I'm working on implementing OAuth 2.0 to a stack of apps I have to reduce the required login credentials. However I am struggeling in understanding the OpenID Connect on top of OAuth 2.0 and how I am supposed to verify the JWT token given. Should the public key be supplied inside the actual token so that the client can check the signature?
Also, correct me if I'm wrong, but I believe this token is never sent to the resource server, but acts as a "helping hand" for the client to serve correct output to the user based on information given in the token? If so, is there a set of standards on what type of information each JWT should contain?
A Identity Token is sent following a Successful Token Response which is typically a JWT.
The ID Token validation is described within Section 3.1.3.7. ID Token Validation.
For ID tokens secured with the RSA or EC signature (e.g. RS256), you need the IdP’s public JSON Web Key (JWK) set. It is published as a simple JSON document at an URL which is also advertised in the OpenID Provider’s metadata] in the jwks_uri parameter. You can check out Google’s JSON Web Key (JWK) to see what such as JWK set looks like.
For ID tokens secured with an HMAC (e.g. HS256) you use the client_secret to perform the validation.

OAuth2.0 what should be the content format of refresh token, before encryption?

I am developing an OAuth2.0 Server. What should be the format of refresh token and what encryption algo should be used for encryption?
OAuth 2.0 does not enforce any restrictions regarding token formats or encryption. Encryption is completely disregarded in the spec, as communication is supposed to be secured with TLS.
Also - don't implement yourself if you don't really have to. Choose an open source library or even a vendor product if your funding permits it.
That being said, take a look at the JWT RFC. That's the format most people use. You can also consider no format at all and just work with opaque strings, and then implement token introspection in your Authorization server.
As to encryption - anything goes. Most implementations out there support at the very least HS256, RS256 and ES256 for signing JWT tokens. In most real world scenarios you don't need to encrypt the token, a signature is enough.
After struggling for sometime, I figured it out. There are two approaches
Either put everything that you need to construct access token (apart from things that can be derived/calculated directly) in refresh token and encrypt it with global or tenant level symmetric key
Benefits:
a. No storage required
b. Better performance as No contact with DB is required. It is just decryption and creation of access token
Issues/shortcomings
a. No way to keep track of refresh tokens issued.
b. No way to invalidate the issued refresh tokens.
Storing attributes related to refresh token in DB and in response of OAuth Server, returning encrypted refresh token ID. Attributes that might be stored in DB are
ID || Expiry || Count of Token || Subject || Client ID || Custom Attributes (If required)
There can be other attributes as well which we implemented but this must give a bit of idea to people who want to implement their own Refresh Token flow

How can I revoke a JWT token?

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.

Resources