Skip to main content

OAuth2 Token Endpoint

Overview

The OAuth2 token endpoint is used to generate access tokens required for accessing protected resources. The available grant types include:

  • authorization_code
  • refresh_token
  • client_credentials
  • urn:ietf:params:oauth:grant-type:jwt-bearer

Base URLs:

  • DEV: https://api.dev.koffi.vn/api
  • UAT: https://api.uat.koffi.vn/api
  • Production: https://uat.koffi.vn/api

Endpoint:

  • URL: /v2/oauth/token
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Headers:
    • Authorization:
      • Depends on grant type authorization will be needed
      • JWT bearer token required for urn:ietf:params:oauth:grant-type:jwt-bearer grant.
      • Basic authentication required for client_credentials grant.

Parameters:

  • grant_type (required): Defines the OAuth2 grant type to be used. Allowed values are:

    • authorization_code
    • refresh_token
    • client_credentials
    • urn:ietf:params:oauth:grant-type:jwt-bearer
  • assertion:

    • The assertion string when using the JWT bearer grant type.
    • Required for JWT Bearer Grant
  • scope (optional): The scopes requested for the token, space-separated. Read scopes for more detail

    • Example: ob.invoices.readonly ob.products.readonly
  • tenant_connection_code:

    • The tenant code for which the token is requested. Defaults to the client application’s tenant if not provided.
    • Required for client_credentials grant
  • code:

    • Authorization code
    • Required for authorization_code grant type
  • refresh_token:

    • Refresh token
    • Required for refresh_token grant type
  • redirect_uri:

    • Redirect uri used in authorization code flow
    • Required for authorization_code and refresh_token grant type
  • code_verifier:

    • Code verifier needed for Authorization Code Flow with PKCE
  • client_id:

    • Client id is needed for public application (SPA, mobile app...) if authorization header was not used

Grant Types and Usage

1. Client Credentials Grant

  • Used by clients to request a token using their client credentials.
  • Read Application for more detail how to get client_id, client_secret, tenant_connection_code.
  • Each tenant in Koffi has a unique connection code. The client application must provide the corresponding connection code when interacting with a specific tenant.
  • Refresh token is not returned in this grant type

Authorization Header:

The Authorization header for this grant type should contain a basic authentication token, which is a base64 encoded string of client_id:client_secret.

Request Example:

curl --location --request POST 'https://api.dev.koffi.vn/api/v2/oauth/token' --header 'Authorization: Basic <base64(client_id:client_secret)>' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'grant_type=client_credentials' --data-urlencode 'scope=ob.invoices.readonly ob.products.readonly' --data-urlencode 'tenant_connection_code=<your_tenant_code>'

Response:

{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600,
"scopes": [
"ob.invoices.readonly",
"ob.products.readonly"
]
}

2. Authorization Code Grant

Authorizaion url

Authorizaion url parameters

  • client_id:
    • Required
    • Application client id
  • redirect_uri:
    • Required
    • One of the registered redirect uri that had been configured for the application
  • scope:
    • Optional
    • Space-separated requested scopes, only require scopes that had been registered for the application.
    • If not given, application'scopes will be used.
  • state:
    • Random state provide by client application, will be returned to client application after completion
  • response_type
    • Token response type after completion
    • Only code is supported
  • code_challenge
    • Required for public client application(SPAs, mobile app...)
    • PKCE challenge code
  • code_challenge_method
    • Optional
    • Algorithm to use when verify code challenge
    • Only S256 is supported

Example authorization code flow

  • This is example for confidential client application(application that can hide/store secret key)

Authorization code flow

  • Authorization request
https://id.dev.koffi.vn/auth?client_id=CLIENT_ID&redirect_uri=https://demo.com&state=123456789
  • After user successfully login and grant consent Koffi will redirect to client application
https://demo.com?code=GENERATED_CODE&state=123456789
  • Client application exchange authorization code for access token and refresh token in back channel using oauth token endpoint
curl --location --request POST 'https://api.dev.koffi.vn/api/v2/oauth/token' --header 'Authorization: Basic <base64(client_id:client_secret)>' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'grant_type=authorization_code' --data-urlencode 'redirect_uri=https://demo.com' --data-urlencode 'code=GENERATED_CODE'

Example authorization code flow with PKCE

  • This is example for public client application(SPAs, mobile app)

Authorization code flow

  • Authorization request
https://id.dev.koffi.vn/auth?client_id=CLIENT_ID&redirect_uri=https://demo.com&state=123456789&code_challenge=Xr4ilOzQ4PCOllhK7l6ORuTz4vQE
  • code_challenge in this example is (base64 url encode of(SHA-256(secret)))
  • After user successfully login and grant consent Koffi will redirect to client application
https://demo.com?code=GENERATED_CODE&state=123456789
  • Client application exchange authorization code for access token and refresh token
curl --location --request POST 'https://api.dev.koffi.vn/api/v2/oauth/token' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'client_id=CLIENT_ID' --data-urlencode 'grant_type=authorization_code' --data-urlencode 'redirect_uri=https://demo.com' --data-urlencode 'code=GENERATED_CODE'
--data-urlencode 'code_verifier=secret'

3. Refresh Token Grant

Refresh token flow

curl --location --request POST 'https://api.dev.koffi.vn/api/v2/oauth/token' --header 'Authorization: Basic <base64(client_id:client_secret)>' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'grant_type=refresh_token' --data-urlencode 'refresh_token=REFRESH_TOKEN' --data-urlencode 'redirect_uri=https://demo.com'

4. JWT Bearer Grant

  • Used by clients to request a token using their JWT Bearer Grant.
  • Read Application for more detail how to get client_id, private_key, public_key, Keypair_id.
  • Use private_key and public_key to generate JWT Bearer Grant.

Generate JWT Bearer Grant:

{
"alg": "RS256",
"typ": "JWT",
"kid": "<your Keypair_id>"
}
Payload
{
"sub": "<prefix_impersonate>:<impersonate>",
"iss": "<your client_id>",
"aud": "<environment>",
"iat": <inti_timestamp>,
"exp": <expire_timestamp>
}

NOTE:

  • prefix_impersonate: possible values: koffi.user.email or koffi.user.id
  • if prefix_impersonate is koffi.user.email then impersonate is email of the user you want to represent
  • if prefix_impersonate is koffi.user.id then impersonate is id of the user you want to represent
data = base64(Header) + "." + base64(Payload)
JWT Bearer Grant = data + "." + RSASHA256(data)

Request Example:

curl --location --request POST 'https://api.dev.koffi.vn/api/v2/oauth/token' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer' --data-urlencode 'scope=ob.invoices.readonly ob.products.readonly' --data-urlencode 'assertion=<your JWT Bearer Grant>'

Response:

{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600,
"scopes": [
"ob.invoices.readonly",
"ob.products.readonly"
]
}

Revoke token

  • Only support revoke refresh token
curl --location --request POST 'https://api.dev.koffi.vn/api/v2/oauth/revoke?token=TOKEN'

Common Authentication Error

Error response

In case of an error, the response will have an HTTP status code other than 200, with the following format

{
"code": "error_code",
"message": "error_message"
}

Error code

  • EOAU401: Unauthorized
  • EOAU201: Invalid grant type
  • EOAU202: JWT Bearer Grant requires assertion
  • EOAU203: JWT Bearer Grant assertion invalid or expired
  • EOAU204: JWT Bearer Grant assertion client id (iss) is required (iss)
  • EOAU205: JWT Bearer Grant assertion key id (kid) is required
  • EOAU206: JWT Bearer Grant assertion key id (kid) is invalid
  • EOAU207: JWT Bearer Grant assertion audience (aud) is required
  • EOAU208: JWT Bearer Grant assertion user not found (sub)
  • EOAU209: Authorization header missing or invalid
  • EOAU210: Authorization code missing, invalid or expired
  • EOAU211: Redirect uri missing or invalid
  • EOAU212: Refresh token missing or invalid
  • EOAU213: Client id missing or invalid
  • EOAU214: Missing code verifier
  • EOAU215: Invalid tenant connection code or client application has no access to target tenant
  • EOAU100: Invalid authorize request info
  • EOAU101: Invalid scope <invalid-scopes>
  • EOAU102: User does not belong to application's organization
  • EOAU103: Application is not published yet
  • EOAU104: Public application requires code challenge