Set up authorisation code grant with PKCE

Proof key for code exchange (PKCE) is an OAuth 2.0 security extension for public clients on mobile devices. You can use it with the Zettle SDK payment apps for enhanced authorisation security.

Instead of using a client secret (requesting tokens), the PKCE method creates a code challenge and includes it in every authorisation request. The received authorisation code and code verifier is then used to request access and refresh tokens. As the code challenge is an encoded code verifier, tokens will be returned only when the code challenge matches the code verifier.

Prerequisites

Step 1: Create code verifier and challenge

  1. Generate a code verifier that fulfills the following rules:

    • Cryptographically create a random string using the characters A-Z, a-z, 0-9, and the punctuation characters -.\_~ (hyphen, period, underscore, and tilde).
    • Make sure that the string is between 43 and 128 characters long.
  2. Create a code challenge by encoding the code verifier with Base64-URL-encoding and SHA256. Base64-URL-encoding uses URL-safe characters for Base64-encoding. For example, change + to -.

    BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
    

Step 2: Initiate the authorisation flow

Include the code challenge in the authorisation request whenever a Zettle merchant authorises the access request from the app.

  1. Present the the following URL in a browser to redirect the merchant to the authorisation flow. The redirect_uri must be the one you provided when creating the SDK app.

    1
    https://oauth.zettle.com/authorize?response_type=code&scope={oauth_scope}&client_id={client_ID}&redirect_uri={redirect_uri}&state={state_value}&code_challenge={code_challenge}&code_challenge_method={code_challenge_method}

    Example: An initiating URL from which the merchant can authorise the app with read and write access to the merchant's payments and user information.

    Request

    1
    https://oauth.zettle.com/authorize?response_type=code&scope=WRITE:PAYMENT%20READ:PAYMENT%20READ:CUSTOMER%20READ:USERINFO&client_id={client_ID}&redirect_uri={redirect_uri}&state=8787&code_challenge={code_challenge}&code_challenge_method=S256
  2. The merchant gets authenticated and authorises the app for data access. When done, the merchant is redirected by the authorisation server to the redirect_uri, together with the authorisation code.

    1
    https://www.example.com/get?code=4fa87ba8cc7f30e91ad2ab1ad21c1b3e&state=abc123678

Step 3: Retrieve access and refresh tokens

Use the temporary authorisation code to retrieve a short-lived access token for first-time access. When it's retrieved, a long-lived refresh token is also returned. The refresh token is used to generate a new access token.

Note: The authorisation code can only be used once.

  1. Retrieve the access and refresh tokens using the authorisation code. This call uses the code_verifier used to generate the code_challenge used in the previous call. Since we don't use a client secret, this code can be called from the client directly.

    1
    curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=authorization_code&code={authorisation_code}&code_verifier={code_verifier}&client_id={client_ID}" https://oauth.zettle.com/token

    Example: Retrieving an access token and refresh token using the authorisation code. The access token is valid for 7200 seconds, and the refresh token is valid for 180 days.

    Request

    1
    curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=authorization_code&code=4fa87ba8cc7f30e91ad2ab1ad21c1b3e&code_verifier=ab190879772...012988&client_id=c55de605-48b6-42ef-b69e-cd9d14ded15a" https://oauth.zettle.com/token

    Response

    1
    {
    2
    "access_token": "eyJraWQiOiIxNDQ0NzI3MTY0Njk4Iiwi...yZA",
    3
    "refresh_token": "IZSEC07b0edfc-f557-4e52-a995-384288e2351e",
    4
    "expires_in": 7200
    5
    }
  2. Save the refresh token for generating a new access token when it expires.

Step 4: Generate a new access token

  1. Use the refresh token to generate a new access token.

    1
    curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=refresh_token&refresh_token={refresh_token}&client_id={client_ID}" https://oauth.zettle.com/token

    Example: Retrieving a new access token using the refresh token.

    Request

    1
    curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=refresh_token&refresh_token=IZSEC90590831-93a5-4289-ee37-a17824c0fea1&client_id=6adde977-c34d-4de1-99b2-f6ed3e65431a" https://oauth.zettle.com/token

    Response

    1
    {
    2
    "access_token": "eyJraWQiOiIxN...R5Y6FDNTva7esJ5Q",
    3
    "refresh_token": "IZSEC07b0edfc-f557-4e52-a995-384288e2351e",
    4
    "expires_in": 7200
    5
    }
  2. Save the new refresh token.

  3. In the next request for generating a new access token, use the new refresh token instead of reusing the current refresh token.

Previous step