Access Token

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


Introduction to Access Token

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

SePay Access Tokens have a limited validity of 1 hour and come with a Refresh Token that has a longer validity of 1 month to obtain new Access Tokens when expired.

Access Token Structure

SePay Access Tokens follow the JWT (JSON Web Token) standard and consist of 3 parts, separated by dots (.):

Signature
header.payload.signature
  • Header: Contains information about the token type and encryption algorithm
  • Payload: Contains claims (information) such as user ID, permission scope, expiration time
  • Signature: Signature to verify the token has not been modified

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 - the token issuer

sub (subject)

ID of the user who granted permission

aud (audience)

Application's Client ID

exp (expiration time)

Token expiration time

iat (issued at)

Time when token was issued

scope

Granted permission scope

Note

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

Using Access Token

To use an Access Token, you need to add it to the Authorization header in each API request with the Bearer prefix:

GET https://my.sepay.vn/api/v1/bank-accounts
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

Here are examples of using Access Token with popular programming languages:

>
>
curl -X GET "https://my.sepay.vn/api/v1/bank-accounts" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Secure Access Token Storage

Securely storing Access Tokens and Refresh Tokens is crucial to protect user data. Below are best practices:

Web Applications (Server-side)

Recommended:

  • Store in server session
  • Store in encrypted database
  • Use cookies with HttpOnly and Secure attributes

Not recommended:

  • Store in localStorage or sessionStorage
  • Store in insecure cookies

SPA (Single Page Application)

Recommended:

  • Use BFF (Backend For Frontend) pattern
  • HttpOnly cookies set from server

Not recommended:

  • Store in localStorage or sessionStorage
  • Store in JavaScript variables

Mobile Applications

Recommended:

  • iOS: Keychain Services
  • Android: EncryptedSharedPreferences
  • Android: Android Keystore System

Not recommended:

  • Unencrypted SharedPreferences
  • Insecure UserDefaults
  • Store in regular application storage
Security Warning

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

Managing Token Expiration

Access Tokens have a limited validity (default is 1 hour). When the token expires, your application needs to handle this situation to maintain a seamless user experience.

Token expiration handling strategies:

  1. Refresh before expiration: Track the expiration time and proactively refresh the token before the API returns an error. You can calculate the refresh time based on the expires_in field in the token response.

  2. Handle 401 error: When the API returns a 401 Unauthorized error code, perform token refresh and retry the request.

Below is sample code for handling token expiration and automatic token refresh:

PHPPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?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 request with new token
return makeApiRequest($url, $accessToken);
}
 
return json_decode($response, true);
}
 
function refreshAccessToken() {
$url = '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', '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 token or request user to login again
401expired_tokenToken has expiredUse refresh token to get new token
403insufficient_scopeToken does not have permission to access resourceRequest new token with broader scope
400invalid_grantRefresh token is invalid or expiredRequest user to login again

Next Step

After understanding how to use and manage Access Tokens, you are ready to learn about SePay API resources: