Skip to main content

JWT Bearer Grant - OAuth2


Previously I wrote a post on my first step towards understanding OAuth. This post continues builds on that. OAuth has different types of flows targeting various scenarios or use cases. The main feature that differentiates each of these flows is the grant type.

What exactly is an OAuth grant type?

An OAuth grant is something that a client application could exchange for an access token from an Authorization Server. An access token typically represents a user's permission for the client application to access the resources on their behalf

OAuth Grant Types

The OAuth 2.0 core specification defines four types of grants,
  • Authorization code grant
  • Implicit grant
  • Resource owner credentials grant
  • Client credentials grant
In addition to these the core specification also defines a refresh grant type.

There are few new additions to these as well,
  • Message authentication code (MAC) tokens
  • SAML 2.0 Bearer Assertion Profiles
  • JSON Web Token grant

I would like to focus on the JSON Web Token Grant in this post. I hope to write my finding about the rest of the grant types in another post.


What is a JWT Bearer Grant?

JSON Web Token bearer grant simply is a json string containing claim values that will be evaluated and validated by the JWT Grant Handlers at the Authroization Server end before issuing an access token. The anatomy of JWT grant,validation process are clearly mentioned in the JSON Web Token (JWT) Profile for OAuth 2.0.

A sample JWT Bearer grant would look like,

{
           "iss":"https://jwt-idp.example.com",
           "sub":"mailto:mike@example.com",
           "aud":"https://jwt-rp.example.net",
           "nbf":1300815780,
           "exp":1300819380,
           "http://claims.example.com/member":true
}

a JWT would have a header declaring the algorithms that will be used to hash and sign the JWT to verified by the token endpoint(Grant Handler).

{
            "alg":"ES256"
}

a JWT will be signed and base64 encoded before sending a POST request to a token endpoint to exchange for an access token like given below,

POST /token.oauth2 HTTP/1.1
Host: authz.example.net
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer &assertion=eyJhbGciOiJSUzI1NiJ9.
eyJleHAiOjE0MjczOTUwODMsInN1YiI6ImZhcmF6YXRoIiwibmJmIjoxNDI3Mzk0NDgzLCJhdWQiOlsiaHR0cHM6XC9cL2xvY2FsaG9zdDo5NDQzXC9vYXV0aDJcL3Rva2VuIiwid3NvMi1JUyJdLCJpc3MiOiJMT0NBTCIsImp0aSI6IlRva2VuNTY3NTYiLCJpYXQiOjE0MjczOTQ0ODN9.
MIXN0t9suRHBnwzG0FZXfetcs1iYcFHax-OLbxF2Vn13-NfzzFYwhKqngFE8BksH1r_2hY0X2XaIU2FlTaUxi1F4pyR59tU55qYnWwYxwhnprOBTqVJormuaBi0olDsyeD8veG_D59Oyp98C8KIGrbjDVblrwoqPCiO3u3W5rrU


The assertion value contains three values separated by a dot,


  • base64urlencoded JWT header
  • base64urlencoded JWT payload
  • Signature (signature is calculated by concatenating the base64 encoded header and the base64 encoded payload and signing it)
    simply, 
    Signature = sign(base64URlEncode(header) + '.' + 
    base64URlEncode
    (payload))

you can easily decode this assertion using jwt-debugger online tool. Simply copy paste the assertion part and you will be enlightened :P

the decoded JWT for the above assertion would be,

{
  "alg": "RS256"
}
{
  "exp": 1427395083,
  "sub": "farazath",
  "nbf": 1427394483,
  "aud": [
    "https://localhost:9443/oauth2/token",
    "wso2-IS"
  ],
  "iss": "LOCAL",
  "jti": "Token56756",
  "iat": 1427394483
}


please note in the post request body the grant_type parameter takes a value of "urn:ietf:params:oauth:grant-type:jwt-bearer" and the assertion parameter value is the signed base64 encoded JWT. The value of the assertion parameter MUST contain a single JWT.

The claim values and how they are validated will be discussed in the latter part of the post along with validation rules.



How does JWT Bearer Grant Work?

By looking at the above diagram, you should be able to get a basic idea. Let me go through the steps


  • A client application authenticates at an identity provider and is issued a JSON Web Toke(JWT) containing the claim values which are mentioned in the latter part of the blog.
  • The identity provider will issue a JWT after successfully authenticating the client.
  • The issued JWT could be used by the client to obtain access tokens from Authorization Servers which the trust the Identity Server that issued the JWT. So simply the Identity Server vouches for your identity and the Authorization Server accepts it trusting the Identity Server.
  • After validating the signature of the identity server in the received assertion and validating the claim values in the issued JWT, the authorization server issues an access token. 



Above diagram should put it all together for you.

Validating a JSON Web Token Bearer Grant

The validation rules specified to JWT Bearer Grant type are quite simple and have some similarities to SAML Bearer grant type as well.

Before jumping into the validation rules lets look at the claim values/ parameters that come with a valid JWT. There are two types of these claims one set is mandatory and the other, yeah you guessed it right "OPTIONAL".

  • Mandatory Values
    • iss (issuer)
    • sub (subject)
    • aud (audience)
    • exp (expiration time)
  • Optional Values
    • nbf (not before)
    • iat (issued at)
    • jti (json web token Id)
    • other custom claims


Rules for validating a JWT bearer grant
  • The JWT MUST contain an iss (issuer) claim that contains a unique identifier for the entity that issued the JWT.
The issuer(iss) value is a string that identifies the Identity Provider or the entity that issued the JWT uniquely.
    • The JWT MUST contain a sub (subject) claim identifying the principal that is the subject of the JWT.
    The subject(sub) value identifies the entity that the identity provider or the entity that issued the JWT vouches for
    • The JWT MUST contain an aud (audience) claim containing a value that identifies the authorization server as an intended audience. The token endpoint URL of the authorization server MAY be used as a value for an aud element to identify the authorization server as an intended audience of the JWT. 
    The audience(aud) value/values are the intended recipients of the JWT denoted by the Identity provider or the JWT issuing entity.
    • The JWT MUST contain an exp (expiration) claim that limits the time window during which the JWT can be used. The authorization server MUST reject any JWT with an expiration time that has passed, subject to allowable clock skew between systems. Note that the authorization server may reject JWTs with an exp claim value that is unreasonably far in the future
    The expiration time(exp) value limits the usage of the JWT beyond the specified value of time. 
    • The JWT MAY contain an nbf (not before) claim that identifies the time before which the token MUST NOT be accepted for processing
    The not before time(nbf) value forces a JWT to be used only after a specified time.
    • The JWT MAY contain an iat (issued at) claim that identifies the time at which the JWT was issued. Note that the authorization server may reject JWTs with an iat claim value that is unreasonably far in the past.
    • The JWT MAY contain a jti (JWT ID) claim that provides a unique identifier for the token. The authorization server MAY ensure that JWTs are not replayed by maintaining the set of used jti values for the length of time for which the JWT would be considered valid based on the applicable exp instant.
    JWT ID(jti) value is an identity value for the JWT issued. This could be used by the entity validating to prevent used JWTs to be replayed. This value need not be unique always which means thats the a JWT with an already validated jti could be reused after a certain threshold value of time determined by the entity validating and the application context.
    • The JWT MAY contain other claims.
    JWT may contain claims other than the above mentioned ones. This really is the extension point of the JWT specification. Custom claims could be made mandatory or optional and their validation logic will depend on the application context.
    • The JWT MUST be digitally signed or have a Message Authentication Code applied by the issuer. The authorization server MUST reject JWTs with an invalid signature or Message Authentication Code.
    The digital signature or the MAC values ensures the integrity of the JWT exchanged between the issuing and the validating entity. The algorithm used for this comes with an inherent vulnerability discussed here.
    • The authorization server MUST reject a JWT that is not valid in all other respects per JSON Web Token (JWT) [JWT].

    Comments

    Popular posts from this blog

    Configuring WSO2 Identity Server to return Attribute Profile claims in SAML SSO Response

    Configuring SAML SSO for an external Service Provider with WSO2 Identity Server is probably one of the most common use cases I heard from my day 1 at WSO2.

    Setting up is quite easy, Just follow the docs here.

    Now let me start from there, what if someone wants to retrieve certain claims of a user in the SAML Response. How easy is it to configure that?

    Well, Let me show you :)

    Step 1

    Assuming that you have setup a Service Provider in Identity Server by following the docs, you should have a configuration like the one below,



    The most important part of this config is the "Enable Attribute Profile" tick, that allows you to get a set of pre-configured claims in the SAML response. Be sure to have it ticked.

    Step 2

    Now your are done with Step 1, In Step 2 you simply configure the claims that you want to be returned in the SAML response. To do this,

    Go to the "Claim Configuration" section of the service provider,


    Now click on "Add Claim URI" and select the claims tha…

    Trying out OAuth2 Authorization Code grant with WSO2 Identity Server without the PlayGround2 App

    The first thing I did after joining the WSO2 Identity Server team was to test the WSO2 Identity Server 5.2.0-beta pack. I had some experience playing around with OAuth so I started testing OAuth scenarios. I was able to test most grant types with ease. Then came the authorization code grant type. The usual way to test it was to setup the playground2 app and test. I wanted to look for an alternate way to test the Authorization grant type without setting up the app (partly because I was lazy to download tomcat etc. :P )

    So with the help of my team member Pushpalanka, I found an alternate way to get an access token by simply using a browser redirect and a curl command. So I wanted to make a note in case someone wanted to do the same :)


    1. First, log in to the Identity Server management console.
           the defaults are,
                      username = admin                   password = admin

    2. Go to the Service Provider configuration page and create a Service Provide, let's say SP_lazy…