OAuth2 Secured Sessions

This page provides a technical and detailed look into the OAuth2 Secured setting within Workflows and Flows.

This feature is a configurable setting in Workflows and Flows. It is designed to mitigate security risks associated with webflows that rely on redirection.

This functionality enforces execution of the flow or workflow as part of an OAuth 2.0 / OpenID Connect (OIDC) authorization flow. In this mode, the onboarding process is executed during the OIDC authorization request and serves as the authentication mechanism, after which the authorization server issues an authorization code upon successful completion.

When the OAuth2 Secured flag is enabled on a Workflow or Flow:

  • A dedicated OIDC client is automatically generated. This OAuth client id is visible in the Workflow/Flow settings after saving. The client is configured with:
    • Authorization Code grant
    • Proof Key for Code Exchange (PKCE) S256
  • The Workflow or Flow execution is part of an OIDC authentication process
  • A redirect URL becomes mandatory.
    • Any future change to this URL must be updated on the Workflow/Flow configuration and all client authorize and token requests. Mismatches result in authorization failures.
  • Disabling and re-enabling the flag regenerates the OAuth client and invalidates the previous client.

When a Workflow or Flow is configured for OAuth security, the old incodesmile URL scheme does not work for that flowid. Customers must move to new URL scheme and authorization pattern described in this document. This ensures there are no security gaps with manual URL tampering.

Security Model

The generated OAuth client uses Proof Key for Code Exchange (PKCE) (RFC 7636) and does not require a client secret. This makes the secured session flow suitable for Single Page Applications (SPAs), mobile applications, or any client unable to securely store secrets.

PKCE protects the authorization code from interception by binding it to a cryptographically generated verifier known only to the client.

OpenID Connect (OIDC) Authorization Flow

The following diagram shows the sequence of a successful onboarding using OIDC:

The following diagram shows the sequence of a failed onboarding using OIDC:

Step 1: Authorization Request (/oauth2/authorize)

Before initiating the authorization request, the client must:

  1. Generate a cryptographically random code_verifier and store it

  2. Compute the code_challenge as a transformation of the code_verifier using Secure Hash Algorithm 256-bit (SHA-256)

  3. Generate state parameter that is used for CSRF protection.

    • cryptographically random value
    • High entropy (random, unguessable)
    • Per authorization request

    See more here.

    Store state in memory for SPA applications or securely in session cookie or in-memory cache (keyed by session) in BFF

  4. Generate nonce parameter that is used to mitigate id replay attacks.

    • High-entropy
    • Unique per authentication request
    • Same quality as state See more here. Store nonce in memory for SPA applications or securely in session cookie or in-memory cache (keyed by session) in a Backends for Frontends (BFF) layer.

Well known endpoint for automatic discovery of configuration, endpoints, and key sets can be found at https://auth.incode.com/.well-known/openid-configuration.

Authorization Request Parameters

ParameterDescription
client_idOAuth Client ID generated and stored in the Workflow/Flow settings.
redirect_uriRedirect URI configured in the Workflow/Flow settings.
response_typecode
scopeopenid
stateOpaque value used to maintain request/response integrity
nonceValue used to associate the ID Token with the client session and prevent replay attacks
code_challenge_methodS256
code_challengeGenerated PKCE challenge
response_modeform_post
external_customer_idId that identifies user in clients external system - optional

Example Authorization Request

https://auth.incode.com/oauth2/authorize
?client_id={client_id}
&redirect_uri={redirect_uri}
&scope=openid
&response_type=code
&response_mode=form_post
&state={state}
&nonce={nonce}
&code_challenge_method=S256
&code_challenge={codeChallenge}
&external_customer_id={external_customer_id}

A breakdown of what this request does:

  • The user is redirected to the Incode Authorization Server.
  • The associated Workflow/Flow is executed as part of the /authorize endpoint
  • On successful onboarding completion:
    • The user is redirected back to redirect_uri
    • An authorization code and state are returned in url
    • Client needs to verify state parameter on callback
      • Compare returned state with stored value. If missing or mismatched → abort process
  • On failed onboarding completion:
    • The user is redirected back to redirect_uri
    • Error and error description url parameters are included (oidc spec).

Step 2: Token Exchange (/oauth2/token)

The client exchanges the authorization code for tokens. Client authenticates using code_verifier generated in Step 1.

Token Request Parameters

ParameterDescription
grant_typeauthorization_code
codeAuthorization code from Step 1
client_idClient ID used in the authorize request
redirect_uriredirect URI used in the authorize request
code_verifierOriginal PKCE code verifier

Example Token Response Body

{
"access_token": "eyJraWQiOiI2MzM2NjAy....zAZ4-FboQg",
"scope": "openid profile",
"id_token": "eyJraWQiOiI2MzM2NjAyYy05....O3dDfO13Yyg",
"token_type": "Bearer",
"expires_in": 86399
}

After a successful response, client must validate ID token. Validation must include:

  • The Issuer Identifier must exactly match the value of the iss (issuer) Claim.
  • The aud (audience) Claim contains its client_id value
  • The JWS signature is verified using the algorithm indicated in the JWT header and the corresponding public key obtained from the Issuer’s well-known JWKS endpoint.
  • The current time must be before the time represented by the exp Claim.
  • The nonce claim must exactly match the nonce value sent by the Client in the authentication request.

Validation of the access token is responsibility of the omni server, and it is done is Step 3.

Step 3: API Access

The access_token issued in Step 2 must be used as a Bearer authorization header (instead of the x-incode-hardware-id header). The token:

  • Is required for accessing Omni APIs
  • Is bound to a single session
  • Adheres to Standard OAuth 2.0 token validation rules

Example curl request with OAuth Secured Workflows/Flows

curl --location 'https://saas-api.incodesmile.com/omni/get/score' \
--header 'Content-Type: application/json' \
--header 'api-version: 1.0' \
--header 'x-api-key: 13cf313e0db1507e77bf8d0631f3ca736173ccde' \
--header 'Authorization: Bearer eyJraWQiOiI2MzM2Nj.....Lf_N7hww'

Endpoints we can call with this token:

  • omni/get/score
  • omni/get/custom-fields
  • omni/get/onboarding/status
  • omni/get/ocr-data