Access Token

Learn how to use and manage Access Tokens to access SePay's APIs.


Introduction to Access Token

  • An Access Token is a string issued by SePay to your application after a successful OAuth2 authentication process. This token acts as a temporary “key” to access SePay’s APIs on behalf of the user.

SePay Access Tokens have a limited lifespan of 1 hour and come with a Refresh Token valid for 1 month to renew a new Access Token when it expires.

Structure of Access Token

  • SePay’s Access Token follows the JWT (JSON Web Token) standard and consists of 3 parts separated by dots (.):

    header.payload.signature
    • Header: Contains information about the token type and encryption algorithm
    • Payload: Contains claims such as user ID, permission scope, and expiration time
    • Signature: The signature used to verify that the token hasn’t been tampered with
  • Example of decoded JWT Access Token content:

RESPONSE
{
  "iss": "https://my.sepay.vn",
  "sub": "12345",
  "aud": "client_67890",
  "exp": 1740541044,
  "iat": 1740537444,
  "scope": "profile bank-account:read transaction:read"
}
iss (issuer)

SePay - token issuer

sub (subject)

ID of the authorized user

aud (audience)

Client ID of the application

exp (expiration time)

Token expiration time

iat (issued at)

Time when the token was issued

scope

Granted access scope

Note

Although JWTs can be decoded to read information, you should not rely on decoding the token on the client side for authentication. The JWT signature can only be verified by SePay.

Using the Access Token

  • To use an Access Token, include it in the Authorization header of each API request with the Bearer prefix:

    GET [https://my.sepay.vn/api/v1/bank-accounts](https://my.sepay.vn/api/v1/bank-accounts) 
    Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL215LnNlcGF5LnZuIiwic3ViIjoidXNlcl8xMjM0NSIsImF1ZCI6ImNsaWVudF82Nzg5MCIsImV4cCI6MTY3OTUzMTQwMiwiaWF0IjoxNjc5NTI3ODAyLCJzY29wZSI6ImJhbmtfYWNjb3VudDpyZWFkIHRyYW5zYWN0aW9uOnJlYWQifQ.signature
  • Below are examples of how to use Access Tokens with popular programming languages:

Secure Storage of Access Tokens

  • Securely storing Access and Refresh Tokens is crucial for protecting user data. Below are best practices:

Web Application (Server-side)

Recommended storage method
  • Store in server-side session
  • Store in encrypted database
  • Use cookies with HttpOnly and Secure attributes
To avoid
  • Storing in localStorage or sessionStorage
  • Using insecure cookies

SPA (Single Page Application)

Recommended storage method
  • Use BFF (Backend For Frontend) pattern
  • Use HttpOnly cookies set from server
To avoid
  • Storing in localStorage or sessionStorage
  • Storing in JavaScript variables

Mobile Application

Recommended storage method
  • iOS: Keychain Services
  • Android: EncryptedSharedPreferences
  • Android: Android Keystore System
To avoid
  • Unencrypted SharedPreferences
  • Insecure UserDefaults
  • Storing in plain app memory
Security Warning

Never store client_secret in client-side or mobile app source code. Always keep client_secret on the server side.

Handling Expired Tokens

  • Access Tokens have a limited lifespan (default: 1 hour). When the token expires, your application must handle it properly to maintain a seamless user experience.

  • Token expiration handling strategies:

    • Refresh before expiration: Track expiration time and refresh proactively before API errors occur. You can calculate the refresh time based on the expires_in field in the token response.
    • Handle 401 errors: When the API returns 401 Unauthorized, refresh the token and retry the request.
  • Below is a sample code to handle token expiration and automatic refresh:

PHP
function makeApiRequest($url, $accessToken) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . $accessToken
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode === 401) {
        // Token expired, refresh token
        $newTokens = refreshAccessToken();
        $accessToken = $newTokens['access_token'];

        // Retry the request with the new token
        return makeApiRequest($url, $accessToken);
    }

    return json_decode($response, true);
}

function refreshAccessToken() {
    $url = '[https://my.sepay.vn/oauth/token';
](https://my.sepay.vn/oauth/token';
)    $data = [
        'grant_type' => 'refresh_token',
        'refresh_token' => 'YOUR_REFRESH_TOKEN',
        'client_id' => 'YOUR_CLIENT_ID',
        'client_secret' => 'YOUR_CLIENT_SECRET',
    ];

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

$bankAccounts = makeApiRequest('[https://my.sepay.vn/api/v1/bank-accounts](https://my.sepay.vn/api/v1/bank-accounts)', 'YOUR_ACCESS_TOKEN');
print_r($bankAccounts);
  • When working with Access Tokens, you may encounter the following errors:
HTTP StatusError CodeDescriptionHandling
401invalid_tokenToken is invalid or expiredRefresh the token or ask the user to log in again
401expired_tokenToken has expiredUse the refresh token to obtain a new one
403insufficient_scopeToken lacks permission to access the resourceRequest a new token with broader permissions
400invalid_grantRefresh token is invalid or expiredAsk the user to log in again

Next Steps

  • After understanding how to use and manage Access Tokens, you are ready to explore SePay’s API resources.