private_key_jwt

Overview


Authlete allows its users to authenticate their clients with a private_key_jwt method, which is defined in OpenID Connect Core 1.0, 9. Client Authentication.


private_key_jwt


When an authorization server authenticates its clients with the private_key_jwt method, the clients must send to the token endpoint of the server a request that contains an assertion in JWT format. And the authorization server must validate the signature and payload of the assertion, which is described as follows.

Client side


The client must send the request that contains the following parameters to the token endpoint when using the private_key_jwt method.
parameter
description
client_assertion_type
a type of client_assertion
client_assertion
a JWT that contains information for client authentication

The value of the client_assertion_type must be like "urn:ietf:params:oauth:client-assertion-type:jwt-bearer".

The value of the client_assertion must be a JWT that contains information for client authentication. Also, the JWT must meet the following requirements.

<Signing>
  • The JWT must be signed using an HMAC SHA algorithm, such as SHA-256. 
  • A public key used for signature verification must be registered at the authorization server.

<Payload>
The JWT must contains the REQUIRED claims listed below
claim
detail
iss
[REQUIRED] Issuer. This must contain the client_id of the OAuth Client.
sub
[REQUIRED] Subject. This must contain the client_id of the OAuth Client.
aud
[REQUIRED] Audience. The aud (audience) Claim. A value that identifies the Authorization Server as an intended audience. The Authorization Server must verify that it is an intended audience for the token. The Audience should be the URL of the Authorization Server's Token Endpoint.
jti
[REQUIRED] JWT ID. A unique identifier for the token, which can be used to prevent reuse of the token. These tokens must only be used once unless conditions for reuse were negotiated between the parties; any such negotiation is beyond the scope of this specification.
exp
[REQUIRED] Expiration time on or after which the ID Token must not be accepted for processing.
iat
[OPTIONAL] Time at which the JWT was issued.

You can find a sample JWT request in the  "Generating an assertion" section.

Server side


Authlete will process the requests following the specifications listed below.


Setting up Authlete for private_key_jwt


You have to set up Authlete to activate the client authentication with private_key_jwt as follows.

Server side


Set up as follows in the service owner console.
section
key
value
authorization
supported client authentication methods
at least contains "PRIVATE_KEY_JWT"

Client side


Set up as follows in the client developer console.
section
key
value
basic
client type
confidential
authorization
assertion signature algorithm


RS256, RS384, RS512,
ES256, ES384, ES512,
PS256, PS384, or PS512

Example


Here, we simulate the client_authentication using private_key_jwt at the token endpoint of the authorization server.

generating an assertion


First, prepare a JWT that will be used as a value of the client_assertion in a token request.

Based on the format of the payload,

{
                                                  "jti":"<この JWT の ID>",
                                                  "sub":"<クライアント ID>",
                                                  "iss":"<クライアント ID>",
                                                  "aud":"<認可サーバーのトークンエンドポイントの URL>",
                                                  "exp":<この JWT の有効期限>,
                                                  "iat":<この JWT が発行されたタイムスタンプ>
                                                }

create a payload json file and save it as "payload.json".

{
                                                  "jti":"myJWTId001",
                                                  "sub":"38174623762",
                                                  "iss":"38174623762",
                                                  "aud":"http://localhost:4000/api/auth/token/direct/24523138205",
                                                  "exp":1536165540,
                                                  "iat":1536132708
                                                }

Then, prepare a JWK set for signing and validating. We use this site to generate a JWK set. The samples below are generated using ES256 algorithm. Here, we save the public and private key pair as "key_pair.jwk". Please make sure to register the public key at the authorization server from Authlete's service owner console.

// public and private key pair
                                                {
                                                  "kty": "EC",
                                                  "d": "ukQKQexNI8PtEv7SKpqUDnbZ-WkN6HaQqcVrVV8ZWRQ",
                                                  "use": "sig",
                                                  "crv": "P-256",
                                                  "x": "9Yxd2TvwBbgmupZh3bpg3umKihM_FNAk2_uI_-Edv_Q",
                                                  "y": "BOUFuyvWoBZ9-RVSeHJLF-L4I3ORv0xbaM1CKCFJr54",
                                                  "alg": "ES256"
                                                }

// public key
                                                {
                                                  "kty": "EC",
                                                  "use": "sig",
                                                  "crv": "P-256",
                                                  "x": "9Yxd2TvwBbgmupZh3bpg3umKihM_FNAk2_uI_-Edv_Q",
                                                  "y": "BOUFuyvWoBZ9-RVSeHJLF-L4I3ORv0xbaM1CKCFJr54",
                                                  "alg": "ES256"
                                                }

As the final step, we generate a payload that includes JWT. The example below is using an authlete-jose library.

$ bin/jose-generator \
                                                --payload-file payload.json \
                                                --sign \
                                                --signing-alg ES256 \
                                                --jwk-signing-alg-file key_pair.jwk

The generated JWT will look like this:

eyJhbGciOiJFUzI1NiJ9.
                                                ewogICJqdGkiOiJteUpXVElkMDAxIiwKICAic3ViIjoiMzgxNzQ2MjM3NjIiLAogICJpc3MiOiIzODE3NDYyMzc2MiIsCiAgImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDAwMC9hcGkvYXV0aC90b2tlbi9kaXJlY3QvMjQ1MjMxMzgyMDUiLAogICJleHAiOjE1MzYxNjU1NDAsCiAgImlhdCI6MTUzNjEzMjcwOAp9Cg.
                                                YB4gdhWUGRjWEsEbKDs7-G2WFH2oYz7bAEP5AtegHXInkY9ncA2V3IoA6O_HVQuFxyCRIklrxsMk32MfNF_ABA

requesting a token


When the client sends a request to the authorization server,

POST /token.oauth2 HTTP/1.1
                                                Host: as.example.com
                                                Content-Type: application/x-www-form-urlencoded
                                              
                                                grant_type=authorization_code&
                                                code=Gw30fMKJBHkcOBSde5awLrMm4ahvgCNM2cFSTUOUflY&
                                                redirect_uri=https://example.com/redirection
                                                client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
                                                client_assertion=eyJhbGciOiJFUzI1NiJ9.
                                                                 ewogICJqdGkiOiJteUpXVElkMDAxIiwKICAic3ViIjoiMzgxNzQ2MjM3NjIiLAogICJpc3MiOiIzODE3NDYyMzc2MiIsCiAgImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDAwMC9hcGkvYXV0aC90b2tlbi9kaXJlY3QvMjQ1MjMxMzgyMDUiLAogICJleHAiOjE1MzYxNjU1NDAsCiAgImlhdCI6MTUzNjEzMjcwOAp9Cg.
                                                                 YB4gdhWUGRjWEsEbKDs7-G2WFH2oYz7bAEP5AtegHXInkY9ncA2V3IoA6O_HVQuFxyCRIklrxsMk32MfNF_ABA

the authorization server will send a request, which is generated according to the request above, to Authlete's /auth/token API,

$ curl -v -X POST https://api.authlete.com/api/auth/token \
                                                -H 'Content-Type: application/json' \
                                                -u '10629969330:tszcLrddM8146JPApzflvRYc7QVU3HhkwCQnoAWF3UI' \
                                                -d '{ 
                                                       "parameters":"grant_type=authorization_code&
                                                                     code=Gw30fMKJBHkcOBSde5awLrMm4ahvgCNM2cFSTUOUflY&
                                                                     redirect_uri=https://example.com/redirection&
                                                                     client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&
                                                                     client_assertion=eyJhbGciOiJFUzI1NiJ9.
                                                                                      ewogICJqdGkiOiJteUpXVElkMDAxIiwKICAic3ViIjoiMzgxNzQ2MjM3NjIiLAogICJpc3MiOiIzODE3NDYyMzc2MiIsCiAgImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDAwMC9hcGkvYXV0aC90b2tlbi9kaXJlY3QvMjQ1MjMxMzgyMDUiLAogICJleHAiOjE1MzYxNjU1NDAsCiAgImlhdCI6MTUzNjEzMjcwOAp9Cg.
                                                                                      YB4gdhWUGRjWEsEbKDs7-G2WFH2oYz7bAEP5AtegHXInkY9ncA2V3IoA6O_HVQuFxyCRIklrxsMk32MfNF_ABA"
                                                    }'

and the client will receive a response as is described below.

{
                                                    "type":"tokenResponse",
                                                    "resultCode":"A050001",
                                                    "resultMessage":"[A050001] The token request (grant_type=authorization_code) was processed successfully.",
                                                    "accessToken":"ni6uDszfkeR5GH96k3cUjt3R7MHG9-xRbMDObaKGY2A",
                                                    ...
                                                }


How did we do with this article?