6.9 KiB
Login
Authenticate a user through the BML web session flow. This involves four sequential HTTP steps before OAuth can begin: seeding cookies, posting credentials, verifying TOTP, and selecting a profile.
All requests in this flow use the web User-Agent and a shared cookie jar that persists cookies (XSRF-TOKEN, blaze_session, blaze_identity) across steps.
Step 1 — Seed Session Cookies
GET https://www.bankofmaldives.com.mv/internetbanking/web/login
This request initialises the session. The server sets the XSRF-TOKEN and blaze_session cookies which must be carried through the entire login flow.
Request
curl --request GET \
--url 'https://www.bankofmaldives.com.mv/internetbanking/web/login' \
--header 'User-Agent: Mozilla/5.0 (Android 14; Mobile; rv:150.0) Gecko/150.0 Firefox/150.0'
Response
200 OK — HTML page. The cookies set in the response headers are the only output needed:
Set-Cookie: XSRF-TOKEN=<token>; Path=/; SameSite=Lax
Set-Cookie: blaze_session=<session>; Path=/; HttpOnly; SameSite=Lax
Extract XSRF-TOKEN from the cookie store for use in Step 2.
Step 2 — Submit Credentials
POST https://www.bankofmaldives.com.mv/internetbanking/web/login
Request
Content-Type: application/json
{
"username": "A123456",
"password": "your_password",
"code": ""
}
| Field | Notes |
|---|---|
username |
BML online banking username (typically the national ID card number) |
password |
Online banking password |
code |
Always empty string "" at this step |
Headers:
| Header | Value |
|---|---|
X-XSRF-TOKEN |
Value of the XSRF-TOKEN cookie from Step 1 |
Content-Type |
application/json |
User-Agent |
Mozilla/5.0 (Android 14; Mobile; rv:150.0) Gecko/150.0 Firefox/150.0 |
curl --request POST \
--url 'https://www.bankofmaldives.com.mv/internetbanking/web/login' \
--header 'Content-Type: application/json' \
--header 'User-Agent: Mozilla/5.0 (Android 14; Mobile; rv:150.0) Gecko/150.0 Firefox/150.0' \
--header 'X-XSRF-TOKEN: <xsrf_token>' \
--cookie 'XSRF-TOKEN=<xsrf_token>; blaze_session=<session>' \
--data '{"username":"A123456","password":"your_password","code":""}'
Response
Success: 302 redirect to /web/login/2fa. The blaze_session cookie is updated.
Failure: Any non-302 response (typically 200 with the login page re-rendered) means the credentials were rejected.
Step 3 — Fetch 2FA Page
GET https://www.bankofmaldives.com.mv/internetbanking/web/login/2fa
This request refreshes the XSRF-TOKEN cookie for the TOTP submission in Step 4. The response body is an HTML page that can be discarded.
curl --request GET \
--url 'https://www.bankofmaldives.com.mv/internetbanking/web/login/2fa' \
--header 'User-Agent: Mozilla/5.0 (Android 14; Mobile; rv:150.0) Gecko/150.0 Firefox/150.0' \
--cookie 'XSRF-TOKEN=<xsrf_token>; blaze_session=<session>'
Extract the fresh XSRF-TOKEN from the updated cookie store before Step 4.
Step 4 — Submit TOTP
POST https://www.bankofmaldives.com.mv/internetbanking/web/login/2fa
Request
Content-Type: application/json
{
"code": "123456",
"channel": "authenticator"
}
| Field | Value | Notes |
|---|---|---|
code |
123456 |
6-digit TOTP from the user's authenticator app |
channel |
authenticator |
Always authenticator for TOTP |
Headers:
| Header | Value |
|---|---|
X-XSRF-TOKEN |
Fresh value from Step 3 |
Content-Type |
application/json |
User-Agent |
Web UA |
curl --request POST \
--url 'https://www.bankofmaldives.com.mv/internetbanking/web/login/2fa' \
--header 'Content-Type: application/json' \
--header 'User-Agent: Mozilla/5.0 (Android 14; Mobile; rv:150.0) Gecko/150.0 Firefox/150.0' \
--header 'X-XSRF-TOKEN: <xsrf_token_2>' \
--cookie 'XSRF-TOKEN=<xsrf_token_2>; blaze_session=<session>' \
--data '{"code":"123456","channel":"authenticator"}'
Response
Success: 302 redirect to /web/profile.
Failure: Any non-302 (typically a 200 with the 2FA page) means the TOTP was invalid. Generate a fresh code and retry.
TOTP Details
BML uses standard RFC 6238 TOTP:
| Parameter | Value |
|---|---|
| Algorithm | HMAC-SHA1 |
| Period | 30 seconds |
| Digits | 6 |
| Encoding | Base32 secret |
Step 5 — Profile Selection
GET https://www.bankofmaldives.com.mv/internetbanking/web/profile
Response — Multi-profile account
200 OK with an HTML page containing an Inertia.js data-page payload. After extracting the Inertia JSON:
{
"props": {
"profiles": [
{
"profile_id": "12345",
"name": "Mohamed Ali",
"type": "Profile",
"profile": {
"profile_type": "default"
}
},
{
"profile_id": "67890",
"name": "My Company Ltd",
"type": "Business",
"profile": {
"profile_type": "business"
}
}
]
}
}
| Field | Type | Description |
|---|---|---|
profile_id |
string |
ID used in Step 6 to activate this profile |
name |
string |
Display name of the profile |
type |
string |
"Profile" for personal, "Business" for business |
profile.profile_type |
string |
"default" (personal) or "business" |
Response — Single-profile account
302 redirect (to /web/redirect or similar). The server has auto-activated the sole profile and set the blaze_identity cookie. Skip Step 6 and proceed directly to OAuth Token Exchange.
Step 6 — Activate Profile
GET https://www.bankofmaldives.com.mv/internetbanking/web/profile/{profile_id}
Replace {profile_id} with the value from the profile list.
curl --request GET \
--url 'https://www.bankofmaldives.com.mv/internetbanking/web/profile/12345' \
--header 'User-Agent: Mozilla/5.0 (Android 14; Mobile; rv:150.0) Gecko/150.0 Firefox/150.0' \
--cookie 'XSRF-TOKEN=<xsrf_token>; blaze_session=<session>'
Response — Personal profile (profile_type: "default")
302 redirect (to /web/redirect or any path other than /web/profile/2fa/business), or 409 Conflict if the profile was already active.
Both outcomes mean success: the blaze_identity cookie is now set. Proceed to OAuth Token Exchange.
Response — Business profile (profile_type: "business")
302 redirect to /web/profile/2fa/business. The business profile requires an additional SMS/email OTP verification step.
Proceed to Business Profile OTP.
Next Steps
- Personal profile activated → proceed to OAuth Token Exchange
- Business profile → proceed to Business Profile OTP
← README Next → Business Profile OTP