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:
{
"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
scopeGranted access scope
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
Authorizationheader of each API request with theBearerprefix:GET [https://my.sepay.vn/api/v1/bank-accounts](https://my.sepay.vn/api/v1/bank-accounts) Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL215LnNlcGF5LnZuIiwic3ViIjoidXNlcl8xMjM0NSIsImF1ZCI6ImNsaWVudF82Nzg5MCIsImV4cCI6MTY3OTUzMTQwMiwiaWF0IjoxNjc5NTI3ODAyLCJzY29wZSI6ImJhbmtfYWNjb3VudDpyZWFkIHRyYW5zYWN0aW9uOnJlYWQifQ.signatureBelow 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)
- Store in server-side session
- Store in encrypted database
- Use cookies with HttpOnly and Secure attributes
- Storing in localStorage or sessionStorage
- Using insecure cookies
SPA (Single Page Application)
- Use BFF (Backend For Frontend) pattern
- Use HttpOnly cookies set from server
- Storing in localStorage or sessionStorage
- Storing in JavaScript variables
Mobile Application
- iOS: Keychain Services
- Android: EncryptedSharedPreferences
- Android: Android Keystore System
- Unencrypted SharedPreferences
- Insecure UserDefaults
- Storing in plain app memory
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_infield in the token response. - Handle 401 errors: When the API returns
401 Unauthorized, refresh the token and retry the request.
- Refresh before expiration: Track expiration time and refresh proactively before API errors occur. You can calculate the refresh time based on the
Below is a sample code to handle token expiration and automatic refresh:
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);Handling Token-related Errors
- When working with Access Tokens, you may encounter the following errors:
| HTTP Status | Error Code | Description | Handling |
|---|---|---|---|
| 401 | invalid_token | Token is invalid or expired | Refresh the token or ask the user to log in again |
| 401 | expired_token | Token has expired | Use the refresh token to obtain a new one |
| 403 | insufficient_scope | Token lacks permission to access the resource | Request a new token with broader permissions |
| 400 | invalid_grant | Refresh token is invalid or expired | Ask 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.