API explorerPay APIsData APIs

Theme switcher

OAuth2

OAuth2 Client Credentials Grant is a method for obtaining access tokens that can be used to authenticate requests to an API. It is typically used when a client (such as a service or application) needs to access resources or APIs on behalf of itself, not on behalf of a user.

How OAuth2 Client Credentials Grant Works

  • The client (service or application) authenticates with the authorization server using its client ID and secret.
  • If the credentials are valid, the authorization server issues an access token.
  • The client uses this access token to authenticate its requests to the resource server (API).

Benefits of OAuth2 Client Credentials

  • Provides a mechanism for API clients to obtain access tokens for authenticating requests.
  • Supports fine-grained authorization and scopes to control access to resources.
  • Enables centralized management of client credentials and access policies.

Private Key JWT

Private Key JWT is a method of client authentication where the client creates and signs a JWT using its own private key. This method is described in a combination of RFC 7521 (Assertion Framework) and RFC 7523 (JWT Profile for Client Authentication), and referenced by OpenID Connect and FAPI 2.0 Security Profile.

Although we support the Client Secret (RFC 6749) authentication, we recommend Private Key JWT as it does not involve a process of sharing secrets.

Setup

Setting up OAuth2 requires a few steps. Please contact us for:

  • Enabling your API Client for OAuth2

  • Sharing the public key which we'll use to verify the signed requests to our Authorization server. Example script for generating the public/private key pair:

    #!/bin/bash
    
    # Generate private key in PEM format
    openssl genpkey -algorithm RSA -out private.key.pem -pkeyopt rsa_keygen_bits:2048
    
    # Generate public key in PEM format (intermediate step)
    openssl rsa -pubout -in private.key.pem -out public.key.pem
    
    # Convert private key to JWK (JSON Web Key) format
    private_jwk=$(openssl rsa -in private.key.pem -noout -text | \
        awk '
        /modulus:/{p=1;next}/publicExponent:/{p=0}p' | \
        tr -d ' \n:' | \
        xxd -r -p | base64 -w 0 | \
        tr '+/' '-_' | tr -d '=')
    
    private_exp=$(openssl rsa -in private.key.pem -noout -text | \
        awk '/privateExponent:/{p=1;next}/prime1:/{p=0}p' | \
        tr -d ' \n:' | \
        xxd -r -p | base64 -w 0 | \
        tr '+/' '-_' | tr -d '=')
    
    # Convert public key to JWK format
    modulus=$(openssl rsa -pubin -in public.key.pem -modulus -noout | \
        cut -d'=' -f2 | \
        xxd -r -p | base64 -w 0 | \
        tr '+/' '-_' | tr -d '=')
    
    # Generate key ID (kid)
    kid=$(openssl rand -hex 32)
    
    # Create public key JWK
    echo "{
      \"kty\": \"RSA\",
      \"kid\": \"$kid\",
      \"n\": \"$modulus\",
      \"e\": \"AQAB\",
      \"alg\": \"RS256\",
      \"use\": \"sig\"
    }" > public.key.json
    
    # Create private key JWK
    echo "{
      \"kty\": \"RSA\",
      \"kid\": \"$kid\",
      \"n\": \"$modulus\",
      \"e\": \"AQAB\",
      \"d\": \"$private_exp\",
      \"alg\": \"RS256\",
      \"use\": \"sig\"
    }" > private.key.json
    
    echo "Keys generated successfully!"
    echo "Files created:"
    echo "- private.key.pem (Private key in PEM format)"
    echo "- private.key.json (Private key in JWK format)"
    echo "- public.key.json (Public key in JWK format)"
    
    # Display the generated kid for reference
    echo -e "\nKey ID (kid) for reference:"
    echo "$kid"
    

Getting an Access Token

Making requests to the Link API in production requires a valid Bearer access token, sent via the standard Authorization header. The process below describes the way to acquire an access token. Example script:

#!/bin/bash

# Your API client id
CLIENT_ID="0o....17"
# The /token endpoint
AUD="https://finqware.okta.com/oauth2/ausfqbxutkZBUKUgQ417/v1/token"
# The key id (kid) of your key
KID="t4cs...j3s"
# Your private key in PEM format
PRIVATE_KEY_PATH="./private.key.pem"

# Generate timestamps
iat=$(date +%s)
exp=$((iat + 3600))

# Create JWT header (Base64URL-encoded)
HEADER=$(echo -n '{"alg":"RS256","typ":"JWT","kid":"'"$KID"'"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')

# Create JWT payload (Base64URL-encoded)
PAYLOAD=$(echo -n '{"aud":"'"$AUD"'","iss":"'"$CLIENT_ID"'","sub":"'"$CLIENT_ID"'","iat":'"$iat"',"exp":'"$exp"',"jti":"'"$(uuidgen)"'"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')

# Combine header and payload
DATA="$HEADER.$PAYLOAD"

# Sign the JWT using RS256
SIGNATURE=$(echo -n "$DATA" | openssl dgst -sha256 -binary -sign "$PRIVATE_KEY_PATH" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')

# Final JWT (signed client_assertion)
JWT="$DATA.$SIGNATURE"

echo "Generated JWT (signed client_assertion):"
echo "$JWT"

echo -e "\n"

# Create the curl command with the generated JWT
echo -e "\nCurl command:"
echo "curl --location --request POST '$AUD' \\
    --header 'Accept: application/json' \\
    --header 'Content-Type: application/x-www-form-urlencoded' \\
    --data-urlencode 'client_id=$CLIENT_ID' \\
    --data-urlencode 'grant_type=client_credentials' \\
    --data-urlencode 'scope=pay_by_link' \\
    --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \\
    --data-urlencode 'client_assertion=$JWT'"

echo -e "\n"
echo -e "\nRetrieving the authz Bearer token..."
curl --location --request POST "$AUD" \
    --header 'Accept: application/json' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode "client_id=$CLIENT_ID" \
    --data-urlencode 'grant_type=client_credentials' \
    --data-urlencode 'scope=pay_by_link' \
    --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
    --data-urlencode "client_assertion=$JWT"

Your backend is responsible to implement a mechanism for keeping an up-to-date access-token available at all times. There are mature libraries for implementing this process, available in all mainstream programming languages (e.g., Java, NodeJS).

Step 1: Build the Client Assertion JWT

Build a token with a payload such as below and sign it with your private key. The signed token is called a client_assertion in OAuth2 terms.

The example below assumes your client_id is xyz123abc and key id (kid): a1b2c3:

JSON Header (must specify your key id):

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "a1b2c3"
}

JSON Payload:

{
  "aud": "https://finqware.okta.com/oauth2/ausfqbxutkZBUKUgQ417/v1/token",
  "iss": "xyz123abc",
  "sub": "xyz123abc",
  "iat": 1741161292,
  "exp": 1741164892,
  "jti": "9CF1E...479C"
}
Step 2: Request Access Token

Use the client_assertion computed above to make a call to our /token endpoint in order to get an access-token:

curl --location --request POST 'https://finqware.okta.com/oauth2/ausfqbxutkZBUKUgQ417/v1/token' \
    --header 'Accept: application/json' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'client_id=xyz123abc' \
    --data-urlencode 'grant_type=client_credentials' \
    --data-urlencode 'scope=pay_by_link' \
    --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
    --data-urlencode 'client_assertion=eyJhbGciOiJSUzI1NiIsIn....le3qGb5mp-yUmPqUwoyZaA9g'
Step 3: Use the Access Token

Use the received access-token for making calls to the Link API until its expiration (each access-token is valid for a limited time).

Include the token in the Authorization header:

Authorization: Bearer your_access_token

Was this section helpful?

What made this section unhelpful for you?

On this page
  • OAuth2
View as Markdown

Ask an AI

Open in ChatGPTOpen in ClaudeOpen in Perplexity

Code with AI

Open in Copilot