Skip to content

PKCE Flow

Why?

In SPA or Mobile apps, it was common to store client_id and client_secret hardcoded. By nature these apps cannot be seen as confidential because the secret can be decompiled.

The PKCE Flow makes it possible to use the Code Flow without the risk of leaking the client_secret.

How

When an application redirects to the /oauth/authorize endpoints two additional paramters need to be added:

  1. code_challenge
    • This is created from another generated variable code_verifier. Allowed characters for the code_verifier are: [A-Z], [a-z], [0-9], "-", ".", "_" and "~", with a minimum length of 43 characters and a maximum length of 128 characters.
      When using the method S256 the code_challenge is the SHA256 Hash value of the code_verifier url safe base64 encoded (without trailing "=").
      When using plain, code_verifier and code_challenge are the same.
  2. code_challenge_method
    • plain (code challenge will be the same as the code_verifier used in /oauth/token call)
    • S256 (recommended)

Steps to perform the flow:

sequenceDiagram
    participant Client
    participant AuthServer as Authorization Server
    participant User

    Client->>AuthServer: Authorization Request (with Code Challenge)
    AuthServer->>User: User Login/Consent
    User-->>AuthServer: User Grant
    AuthServer-->>Client: Authorization Code
    Client->>AuthServer: Token Request (with Authorization Code and Code Verifier)
    AuthServer->>AuthServer: Validate Authorization Code and Code Verifier
    AuthServer-->>Client: Access Token, Refresh Token
    Client->>AuthServer: Userinfo Request (with Access Token)
    AuthServer->>AuthServer: Validate Access Token
    AuthServer-->>Client: Userinfo Response
  1. User clicks login in application
  2. Redirect to Unidy is performed including the Parameters required for the authorization request
    • response_type parameter is set to code
    • code_challenge is filled with generated challenge
    • code_challenge_method is set to either plain or S256
  3. Unidy asks the User to login if not logged in yet
  4. Unidy requires user to fill out missing profile data if Required User Attributes are configured
  5. Unidy redirects back to the redirect_uri including a code paramter as fragment as default
    • when using response_mode form_post Unidy sends the code as form post
  6. Application extracts the code and sends the code to the /oauth/token endpoint with paramters below as json.

    Parameter Content
    client_id Unique identifier that corresponds to one of the UIDs in Unidys partner Applications (provided by Unidy)
    client_secret Application secret provided by Unidy.(Must be stored securely)
    redirect_uri Endpoint where the data from Unidy should be returned to (must be https)
    grant_type Must be set to authorization_code
    code code obtained from authorization
    code_verifier Verifier to generate code_challenge with code_challenge_method provided in authorization call
  7. Unidy responds with:

    {
        "access_token": "zuc7faJYHTGqAn9z84Q6X4qyyfAVEbJOicsADSqBTM0",
        "token_type": "Bearer",
        "expires_in": 7200,
        "refresh_token": "HMNTpMQZPGqnff5MgLQuA2GMw_VG5JAaVIHFccOWKeI",
        "scope": "openid",
        "created_at": 1687446442,
        "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlYyck9HQnZVR2dLZG1fRHhGUzdfS1EtRUUzTXBfdlVkUnBQODlJY2xrMVEifQ.eyJpc3MiOiJodHRwczovL2J0Yy1lY2hvLnN0YWdpbmcudW5pZHkuZGUiLCJzdWIiOiJjOTVkNWQ3NS0wYjMyLTQyNzgtODMwNi0wYWRjZDE5NThhNWIiLCJhdWQiOiI5dHUxek1PU095bVoycUluaEZfNDZITl9xemdxY2M3MTBDUzI5NmlPSVRBIiwiZXhwIjoxNjg3NDQ2NTYyLCJpYXQiOjE2ODc0NDY0NDIsIm5vbmNlIjoiNThqZzMyeGQweG8iLCJhdXRoX3RpbWUiOjE2ODc0NDYxNzB9.ioVQsiM5nYkUS1zuwfgYvWGtTgH1bibV6MdeXCDJxrifnUBFxHg-CHVUeftkk0ZGZWSlvbkN62WR_FI43rwJbTIocEXmWGoG-EML738pT1zvRvDrO3hskExg51AwICUswIjENNxCdVSqCWWWMvTs0UgcwA55DauCZNqoJxkpOjY05kdFhOnCxCJ1q903L3r7Rw43yVXRQtzc-3sDnzog0wIm7w9Ysq6JoyUdmRw9ng5-fvEEu_ou9EDwVTfZ5PzTF-pfQXu-wsLWJExLT89lzEqjyd568lnJAtsj-q4JiJ-p3Dsu7B4nSprOU6BqeVZQnFMJJJFrqCviaqarFenaQQ"
    }
    

  8. Application uses access token to fetch user data from /oauth/userinfo endpoint. The access token must be set within the authorization header

    Authorization: Bearer <YOUR ACCESS TOKEN>

Refresh Access Token

Access Tokens will expire after 2 hours. You can refresh the access token without user interaction by using the provided refresh token. To refresh an access token you need to call the /oauth/token endpoint with the following paramters:

{
   "refresh_token":"<YOUR REFRESH TOKEN>",
   "grant_type":"refresh_token",
   "client_id":"<YOUR CLIENT ID>",
   "client_secret": "<YOUR SECRET>"
}