Files
thijooree/docs/bmlapi/03-oauth-token.md
Shihaam Abdul Rahman 0a27de4a34
All checks were successful
Auto Tag on Version Change / check-version (push) Successful in 5s
update bml api docs
2026-05-23 23:33:31 +05:00

6.5 KiB

OAuth Token Exchange and Refresh

After the web login flow has set the blaze_identity cookie (profile activated), the client exchanges a PKCE authorization code for an access_token and refresh_token. These tokens are used for all subsequent REST API calls.


Prerequisites

  • Completed Login (and Business OTP if applicable)
  • blaze_identity cookie set in the session
  • PKCE code_verifier and code_challenge generated at the start of the login session
  • Device-ID generated at the start of the login session

PKCE Parameter Generation

Generate these once at the start of each login session:

Parameter Generation
code_verifier 72 cryptographically random bytes, base64url-encoded (no padding)
code_challenge SHA-256 hash of code_verifier (as ASCII bytes), base64url-encoded (no padding)
Device-ID 8 cryptographically random bytes, hex-encoded (16 hex chars)
state 16 random bytes, base64url-encoded
nonce 12 random bytes, base64url-encoded

Step 1 — Authorize (Get Auth Code)

GET https://www.bankofmaldives.com.mv/internetbanking/oauth/authorize

Query Parameters

Parameter Value
redirect_uri https://app.bankofmaldives.com.mv/oauth/mobile-callback
client_id 98C83590-513F-4716-B02B-EC68B7D9E7E7
response_type code
state Random base64url string (16 bytes)
nonce Random base64url string (12 bytes)
code_challenge SHA-256 of code_verifier, base64url-encoded
code_challenge_method S256
Device-ID Random 16-char hex string
User-Agent App user agent string
x-app-version 2.1.44.348
curl --request GET \
  --url 'https://www.bankofmaldives.com.mv/internetbanking/oauth/authorize?redirect_uri=https%3A%2F%2Fapp.bankofmaldives.com.mv%2Foauth%2Fmobile-callback&client_id=98C83590-513F-4716-B02B-EC68B7D9E7E7&response_type=code&state=<state>&nonce=<nonce>&code_challenge=<code_challenge>&code_challenge_method=S256&Device-ID=<device_id>&User-Agent=bml-mobile-banking%2F348+%28Xiaomi%3B+Android+14%3B+22101320I%29&x-app-version=2.1.44.348' \
  --header 'User-Agent: Mozilla/5.0 (Android 14; Mobile; rv:150.0) Gecko/150.0 Firefox/150.0' \
  --cookie 'blaze_session=<session>; blaze_identity=<identity>'

Response

302 redirect to:

https://app.bankofmaldives.com.mv/oauth/mobile-callback?code=<auth_code>&state=<state>

Extract the code query parameter from the Location header. This is the one-time authorization code.


Step 2 — Token Exchange

POST https://www.bankofmaldives.com.mv/internetbanking/oauth/token

Request

Content-Type: application/x-www-form-urlencoded

Field Value
grant_type authorization_code
code Auth code from Step 1
code_verifier PKCE verifier generated at login start
client_id 98C83590-513F-4716-B02B-EC68B7D9E7E7
redirect_uri https://app.bankofmaldives.com.mv/oauth/mobile-callback
Device-ID Same device ID used in Step 1
User-Agent App user agent string
x-app-version 2.1.44.348
curl --request POST \
  --url 'https://www.bankofmaldives.com.mv/internetbanking/oauth/token' \
  --header 'User-Agent: Mozilla/5.0 (Android 14; Mobile; rv:150.0) Gecko/150.0 Firefox/150.0' \
  --data 'grant_type=authorization_code' \
  --data 'code=<auth_code>' \
  --data 'code_verifier=<code_verifier>' \
  --data 'client_id=98C83590-513F-4716-B02B-EC68B7D9E7E7' \
  --data 'redirect_uri=https%3A%2F%2Fapp.bankofmaldives.com.mv%2Foauth%2Fmobile-callback' \
  --data 'Device-ID=<device_id>' \
  --data 'User-Agent=bml-mobile-banking%2F348+%28Xiaomi%3B+Android+14%3B+22101320I%29' \
  --data 'x-app-version=2.1.44.348'

Response

{
  "access_token": "eyJhbGciOiJSUzI1NiJ9...",
  "refresh_token": "def50200aabbcc...",
  "token_type": "Bearer",
  "expires_in": 3600
}
Field Type Description
access_token string JWT Bearer token — use in Authorization: Bearer <token> on all REST API calls
refresh_token string Long-lived token — use to refresh without re-login
token_type string Always "Bearer"
expires_in number Token lifetime in seconds (typically 3600)

Store access_token, refresh_token, expires_in, and Device-ID together as the session. The access_token expires at now + expires_in * 1000 milliseconds.


Token Refresh

When the access token expires (on 401 or 419 from any REST endpoint), obtain a new one using the refresh token. No web session or cookies are needed.

POST https://www.bankofmaldives.com.mv/internetbanking/oauth/token

Request

Content-Type: application/x-www-form-urlencoded

Field Value
grant_type refresh_token
refresh_token Stored refresh token
client_id 98C83590-513F-4716-B02B-EC68B7D9E7E7
Device-ID Same device ID from the original login
User-Agent App user agent string
x-app-version 2.1.44.348
curl --request POST \
  --url 'https://www.bankofmaldives.com.mv/internetbanking/oauth/token' \
  --header 'User-Agent: bml-mobile-banking/348 (Xiaomi; Android 14; 22101320I)' \
  --data 'grant_type=refresh_token' \
  --data 'refresh_token=def50200aabbcc...' \
  --data 'client_id=98C83590-513F-4716-B02B-EC68B7D9E7E7' \
  --data 'Device-ID=a1b2c3d4e5f60718' \
  --data 'User-Agent=bml-mobile-banking%2F348+%28Xiaomi%3B+Android+14%3B+22101320I%29' \
  --data 'x-app-version=2.1.44.348'

Response

Same structure as the token exchange response. The server may issue a new refresh_token (rotating tokens). If a new one is returned, replace the stored value; otherwise keep the original.

{
  "access_token": "eyJhbGciOiJSUzI1NiJ9...<new>",
  "refresh_token": "def50200...<new or same>",
  "token_type": "Bearer",
  "expires_in": 3600
}

Failure: If access_token is absent or blank in the response, the refresh token has expired. Re-run the full login flow.


Session Storage

Persist the following to represent a saved BML session:

Field Description
access_token Bearer token for REST API calls
refresh_token Used to renew without re-login
expires_at Unix timestamp (ms) when access_token expires
device_id Must be sent with every refresh; ties tokens to the device

 


← Business Profile OTP     Next → Dashboard