Overview
The token endpoint is the core authentication endpoint that issues access tokens and refresh tokens. It supports multiple grant types for different authentication flows:
OTP Grant (urn:masareagle:otp) - Passwordless authentication for drivers and passengers using phone number + OTP
Password Grant (password) - Traditional username/password authentication for admin and company users
Refresh Token Grant (refresh_token) - Exchange a refresh token for new access tokens
This endpoint follows the OAuth 2.0 and OpenID Connect specifications and is powered by OpenIddict.
Authentication
This endpoint does not require authentication. Credentials are provided in the request body.
Grant Types
OTP Grant (Passwordless)
Authenticate using a phone number and OTP code. This is the primary authentication method for drivers and passengers.
Must be urn:masareagle:otp for OTP-based authentication
The phone number with country code (e.g., +966501234567)
The 6-digit OTP code received via SMS
The type of user authenticating. Allowed values:
Driver - For driver users
Passenger - For passenger users
Admin - For admin users (OTP auth)
Company - For company users (OTP auth)
Password Grant
Authenticate using username (email) and password. Only available for Admin and Company user types.
Must be password for password-based authentication
The type of user authenticating. Only Admin and Company are supported for password grant.
Refresh Token Grant
Exchange a valid refresh token for new access and refresh tokens.
The refresh token obtained from a previous token request
Response
The JWT access token used to authenticate API requests. Include this in the Authorization header as Bearer {access_token}.
The lifetime of the access token in seconds (typically 3600 for 1 hour)
The refresh token that can be used to obtain new access tokens without re-authenticating
The scopes granted to the access token: openid offline_access roles api
OpenID Connect ID token containing user identity claims
Token Claims
The access token includes the following claims:
sub (Subject) - The user’s unique identifier
role - The user type (Driver, Passenger, Admin, Company)
aud (Audience) - Always masar-eagle-api
exp (Expiration) - Token expiration timestamp
iat (Issued At) - Token issuance timestamp
cURL - OTP Grant
cURL - Password Grant
cURL - Refresh Token Grant
JavaScript - OTP Grant
Python - OTP Grant
C# - OTP Grant
curl -X POST https://api.masareagle.com/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=urn:masareagle:otp" \
-d "phone_number=+966501234567" \
-d "otp_code=123456" \
-d "user_type=Driver"
200 Success - OTP Grant
200 Success - Password Grant
403 Invalid OTP
403 Invalid Phone Number
403 Invalid Credentials
403 User Type Required
403 Invalid Grant Type
403 Password Grant Not Allowed
403 Invalid Refresh Token
{
"access_token" : "eyJhbGciOiJSUzI1NiIsImtpZCI6IjEyMzQ1Njc4OTAiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiI0MjEzZjhjOC0xYzJhLTQxZTAtYmU2Yy1kYzJhNWY1YzI4ZmYiLCJyb2xlIjoiRHJpdmVyIiwiYXVkIjoibWFzYXItZWFnbGUtYXBpIiwiZXhwIjoxNzA5ODI3MjAwLCJpYXQiOjE3MDk4MjM2MDB9..." ,
"token_type" : "Bearer" ,
"expires_in" : 3600 ,
"refresh_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MjEzZjhjOC0xYzJhLTQxZTAtYmU2Yy1kYzJhNWY1YzI4ZmYiLCJleHAiOjE3MTI0MTU2MDB9..." ,
"scope" : "openid offline_access roles api" ,
"id_token" : "eyJhbGciOiJSUzI1NiIsImtpZCI6IjEyMzQ1Njc4OTAiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiI0MjEzZjhjOC0xYzJhLTQxZTAtYmU2Yy1kYzJhNWY1YzI4ZmYiLCJyb2xlIjoiRHJpdmVyIn0..."
}
Authentication Flow
OTP Authentication Flow
User enters their phone number in your app
Call Send OTP endpoint to generate and send OTP
User receives OTP via SMS (6-digit code)
User enters OTP code in your app
Call /connect/token with grant_type=urn:masareagle:otp
Store the returned access_token and refresh_token securely
Include access_token in subsequent API requests: Authorization: Bearer {access_token}
Token Refresh Flow
When access token expires (check expires_in or handle 401 responses)
Call /connect/token with grant_type=refresh_token
Store the new access_token and refresh_token
Retry the original request with new access token
Password Authentication Flow
User enters email and password in your app
Call /connect/token with grant_type=password
Store tokens securely
Use access token for API requests
Security Best Practices
Token Storage:
Never store tokens in localStorage for web apps (use httpOnly cookies or secure storage)
For mobile apps, use platform-specific secure storage (Keychain on iOS, Keystore on Android)
Never log or expose tokens in error messages
Token Usage:
Always use HTTPS for token requests
Implement token refresh logic before expiration
Clear tokens on logout
Rotate refresh tokens periodically
Client Implementation:
Implement automatic token refresh when receiving 401 responses
Handle race conditions when multiple requests need token refresh
Set up token expiration monitoring
Implement secure token storage per platform
User Provisioning
When a user authenticates via OTP for the first time, the system automatically provisions a user account:
Token endpoint publishes UserAuthenticatedEvent with phone number and user type
Users service consumes the event and creates a user record if it doesn’t exist
Token endpoint resolves the user ID and issues tokens
If user is not provisioned yet (race condition), the endpoint waits 1 second and retries
This ensures seamless onboarding without requiring explicit registration.
Implementation Details
The endpoint (src/services/Identity/src/Identity.Web/TokenEndpoint.cs):
Parses the OpenIddict request context
Routes to appropriate grant handler based on grant_type
Validates credentials (OTP, password, or refresh token)
Creates claims identity with user ID and role
Sets scopes: openid, offline_access, roles, api
Sets audience: masar-eagle-api
Signs in using OpenIddict to generate tokens
Returns OAuth 2.0 token response
Error Handling
All errors follow OAuth 2.0 error response format with:
error - Standard OAuth 2.0 error code
error_description - Human-readable error message (in Arabic)
Common error codes:
invalid_request - Missing or invalid required parameters
invalid_grant - Invalid credentials, expired OTP, or user not found
unsupported_grant_type - Unsupported grant type
Source Code Reference
Token Endpoint: src/services/Identity/src/Identity.Web/TokenEndpoint.cs
OTP Grant Handler: src/services/Identity/src/Identity.Web/TokenEndpoint.cs:51
Password Grant Handler: src/services/Identity/src/Identity.Web/TokenEndpoint.cs:122
Refresh Grant Handler: src/services/Identity/src/Identity.Web/TokenEndpoint.cs:152
OpenIddict Configuration: src/services/Identity/src/Identity.Web/OpenIddictServerConfiguration.cs
User Types: src/services/Identity/src/Identity.Core/Constants/UserTypes.cs