🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
OpenIdConnect access token and refresh token
This page was created by Hans.karlsen on 2023-09-30. Last edited by Wikiadmin on 2026-07-29.

You can use the access token issued when a user signs in through OpenID Connect to call APIs on that user's behalf, and refresh that token from a ViewModel when it has expired or before a new API operation.

What this feature does

When a user signs in through OpenID Connect, Turnkey can exchange the authorization code returned by the identity provider for tokens. It stores the resulting tokens as claims for that user:

ClaimType Purpose
access_token A short-lived token that you send when calling an API that accepts the signed-in user's delegated access.
refresh_token A longer-lived token that Turnkey uses to request a new access token without requiring another interactive sign-in.

The claims are represented by SysUserClaim objects associated with the signed-in SysUser. For example, after a successful Azure AD sign-in, the user's claims can include both access_token and refresh_token, in addition to claims received from the identity provider.

This is a user-delegated token flow: the token represents the signed-in user and the API still enforces that user's permissions. For example, an API request for a document can succeed only when both the application registration and the signed-in user have permission to access that document.

Configure token acquisition

Configure OpenID Connect before users sign in. Put deployment-specific settings in App_Data/TurnkeySettingsOverride.xml so that an upgrade does not replace them. See Documentation:OpenID config for the complete OpenID Connect configuration and provider-specific setup.

The settings required for access-token refresh are:

Setting Required value or purpose
OpenID_TokenEndPoint The identity provider's token endpoint. Turnkey uses this endpoint to exchange the authorization code and later refresh the access token.
OpenIDConnectScope Must include offline_access when using Azure AD. Include the OpenID and API scopes that your sign-in and API call require.
SharedSecret A secret that Turnkey uses to encrypt the stored tokens in the database. Keep this value private and outside the application model.

Example settings structure:

<OpenID_TokenEndPoint>yourserverTokenEndpointUsuallyEndsLikeThis/oauth2/v2.0/token</OpenID_TokenEndPoint>
<OpenIDConnectScope>offline_access openid profile</OpenIDConnectScope>
<SharedSecret>Secret</SharedSecret>

For Azure AD, offline_access is required for Azure AD to issue a refresh token. Without a refresh token, Turnkey cannot obtain a new access token after the current one expires; the user must sign in again.

Also configure the identity provider with the exact callback URL used by Turnkey. A callback ending in /signin-oidc helps the middleware recognize the provider's login callback. The provider must allow the configured redirect URL. See Documentation:OpenID config for redirect URL guidance and Documentation:How does OpenIdConnect work for the authorization-code flow.

Refresh the access token from a ViewModel

Add the following method to SysUser in your model:

OpenIdConnectAccessTokenRefresh():String (TV: Eco.ExternalLateBound)

Call this method before an operation that requires a current access token.

  1. Identify the SysUser for the signed-in user.
  2. Call OpenIdConnectAccessTokenRefresh() on that user.
  3. Check the returned string.
  4. If the result is ok, read the updated SysUserClaim values whose ClaimType values are access_token and refresh_token.
  5. Use the current access_token for the API request.
  6. If the result is an error, do not continue with the API request. Handle the error and require the user to sign in again when a valid refresh token is no longer available.

The access token is short-lived. Refresh it before starting a new API operation rather than assuming a token obtained at login is still valid. A refresh can also return an updated refresh token, so always use the claim values after a successful refresh instead of retaining an older token value.

Example operation sequence

A document integration that calls a delegated API can follow this sequence:

  1. The user signs in through OpenID Connect.
  2. Turnkey receives the authorization code at the configured callback and obtains the initial tokens.
  3. Turnkey stores the encrypted token values as the user's claims.
  4. Before requesting a document, the ViewModel calls OpenIdConnectAccessTokenRefresh().
  5. When the method returns ok, the ViewModel uses the updated access_token in its API request.

If the refresh token has been revoked, has expired, or is otherwise no longer accepted by the identity provider, a refresh cannot restore access. The user must sign out and sign in again so that the provider can issue a new authorization code and, where permitted, a new refresh token.

Security and operational requirements

  • Treat both token claims as credentials. Do not expose them in UI, logs, diagnostics, or client-side data.
  • Set a private, deployment-specific SharedSecret. It encrypts the stored tokens and is particularly important because refresh tokens can remain usable longer than access tokens.
  • Keep the shared secret outside the model and restrict access to the Turnkey settings files and database backups.
  • Request only the API scopes needed by the integration. The identity provider's application registration must also be permitted to use the target API.
  • Configure each environment's permitted redirect URL at the identity provider. Local, test, and production URLs are distinct values.

Troubleshooting

Symptom Check
No refresh_token claim after sign-in Confirm that OpenIDConnectScope contains offline_access for Azure AD and that the identity provider accepted the requested scope.
Refresh returns an error Confirm OpenID_TokenEndPoint, the application secret, and provider configuration. The refresh token may also have expired or been revoked; sign in again.
Login returns to the application but the authorization code is not handled Confirm that the configured and provider-registered redirect URLs match exactly. Use a redirect ending in /signin-oidc when applicable.
API request is denied although token refresh succeeds Check both the application registration's granted API permissions and the signed-in user's permission to the requested resource.

For OpenID Connect logging and diagnosis of the authorization-code callback, see Documentation:How does OpenIdConnect work.

Scope of this page

This page covers refreshing tokens obtained through an interactive OpenID Connect user login. Do not use this pattern for server-to-server access with no signed-in user; use HowTos:Oauth2 Client Credentials Grant Flow instead. For the earlier Office 365-specific approach and Graph API background, see Documentation:Office365 accesstoken.

See also