Connect desktop, mobile, or browser applications (authorization code grant flow with PKCE)

Desktop, mobile and stand-alone browser applications are considered public clients because there’s no separate server with controlled access. Proof Key for Code Exchange (PKCE) provides a secure way to use the authorization code grant flow with public clients.

See more information on the available flows and how to choose the correct one for your case.

PKCE secures the authentication by using a request-specific code challenge and code verifier.

To summarize the process, your client application must send two requests:

  1. Send the first request to the authorization endpoint (/user/oauth20/authz) of the 10Duke Authentication API. This request must include a code challenge derived from the code verifier.

    The server responds by redirecting back to the client with an authorization code.

  2. Send the second request to the access token endpoint (/user/oauth20/token) to exchange the authorization code for an access token.

    This request must include a code verifier that corresponds to the code challenge you sent. This way the server can ensure that it’s returning the access token to your client application and not to someone who has stolen the authorization code during the process.

Before you start

  • Define an OIDC connection for your client application in 10Duke SysAdmin.

    • This includes defining the client ID (OAuth client_id) for your client application, the authentication flow used, and the redirect URI for receiving the OAuth authorization code.

    • If your client application uses an in-app browser, a custom URI scheme is usually used for the redirect URI. If a standard browser is used, your application needs to be able to receive the redirect request from the browser running on the same system (an HTTP request to localhost).

  • The following steps assume that your application has access to a browser to show the login dialog to the end user.

    If you’re connecting an application that doesn’t already support user login, your application must be modified to do so. See the available 10Duke Enterprise SDKs and client libraries.

Step 1: Generate code verifier

In the client application, generate a code verifier for the authentication request, and use it to derive a code challenge. Store the code verifier for later use.

The code verifier is a random string of 43-128 characters that can contain alphanumeric characters, - (dashes), . (dots), _ (underscores) and ~ (tildes).

The recommended method for deriving the code challenge is S256. Compute an SHA-256 hash of the code verifier and encode it with a URL-safe Base64 encoding according to the specification.

An example S256 code challenge:

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

Step 2: Initiate authentication flow

Initiate the authentication flow from the client application by navigating to the 10Duke Enterprise authentication/authorization endpoint.

An example URL for this request (line breaks added for display purposes):

<BASE_URL>/user/oauth20/authz
   ?response_type=code
   &client_id=79w1-6s41-4s7x-8e96-76u986gs1
   &redirect_uri=client%3Acustomer
   &scope=openid%20profile%20email
   &code_challenge_method=S256
   &code_challenge=X2YHD2BztPSx9-Iw9QJQUF4JF6ypgDywhHWOqpPJ8x8
   &state=AnyStateFromClient

Provide actual values in client_id, redirect_uri, code_challenge_method, and code_challenge.

In scope, provide the requested OAuth scopes. This must contain at least openid.

Optional parameters:

  • If the user is not logged in yet, by default the login page is opened for them. With flow=register, you can request to open the registration page instead.

  • Provide the user’s email address in login_hint, which enables 10Duke Enterprise to automatically populate the email address field so the user doesn’t have to fill it in again.

  • state can be anything that the client application wants to get back after login.

When the end user has completed the login in the browser and been successfully authenticated, the browser is redirected back to the client application’s redirect URI.

Step 3: Extract authorization code

Handle the redirect request in the client application, and extract the authorization code that was sent with the request in the code query parameter.

An example redirect request (line breaks added for display purposes):

client:customer
   ?code=hdgkv5rkant5o5f08150hmtq1l
   &state=AnyStateFromClient

Step 4: Get access token

To exchange the authorization code for an access token, send an HTTPS POST request to the 10Duke Enterprise access token endpoint.

An example curl call (line breaks added for display purposes):

curl
   --url '<BASE_URL>/user/oauth20/token'
   --header 'Content-Type: application/x-www-form-urlencoded'

   --data 'grant_type=authorization_code'
   --data 'redirect_uri=client:customer'
   --data 'client_id=79w1-6s41-4s7x-8e96-76u986gs1'
   --data 'code_verifier=88DccPNbKI1E4NlAsbBcO06W_Yn~UlONrF4iYoyWMRq0D~RRjLGZO9-P2mTeL4Ih'
   --data 'code=hdgkv5rkant5o5f08150hmtq1l'

Set the content header to Content-Type: application/x-www-form-urlencoded.

In the form data (the request body), use grant_type=authorization_code, and provide actual values in redirect_uri, client_id, code_verifier, and code (the authorization code).

A successful call should return a response like this:

{
   "access_token": "ACCESS_TOKEN_VALUE",
   "remember":false,
   "refresh_token": "REFRESH_TOKEN_VALUE",
   "scope":"openid profile"
   "id_token": "ID_TOKEN_VALUE",
   "token_type": "Bearer",
   "expires_in": 3600,
   "issued_at":1675702153
   "refresh_token_expires_in":86400
}

Your client application can use access_token to authorize 10Duke API requests, refresh_token (if granted and included in the response) for requesting new access tokens, and id_token to read user details. refresh_token_expires_in contains the seconds until the OAuth session expires, after which the client application can no longer refresh the access token.

The response fields may vary depending on the 10Duke Enterprise release. Make sure your client application is able to handle the response if new fields are added. The response can also contain additional fields depending on possible customizations.

Next steps

After a successful authentication, your client application can: