Mobile PKCE Integration
This recipe describes how a native mobile app can use Muhajir Studio with Authorization Code Flow with PKCE.
Supported Redirect Model
Muhajir Studio application registration is based on HTTP(S) web origins plus redirect paths. For production mobile apps, use a verified HTTPS redirect URI handled by Universal Links or Android App Links.
| Service | Production URL | Used for |
|---|---|---|
| API | https://api.muhajirstudio.com/ | Authorization, token exchange, refresh, and external APIs. |
| Main web | https://login.muhajirstudio.com/ | Hosted login, signup, verification, and consent. |
| Admin web | https://admin.muhajirstudio.com/ | Application registration. |
Custom URL schemes such as myapp://callback are not valid allowedWebOrigins in the current registration model. Use an HTTPS app link such as https://app.example.com/mobile/callback.
Admin Setup
Register the mobile application with:
| Field | Example | Notes |
|---|---|---|
| Allowed web origin | https://app.example.com | HTTPS origin controlled by your app/team. |
| Redirect path | /mobile/callback | Path opened by your Universal Link or App Link handler. |
| Redirect URI | https://app.example.com/mobile/callback | Derived from origin + path. |
| Scopes | openid profile email offline_access | Include offline_access only when long-lived sessions are required and supported. |
1. Open the System Browser
Use the platform's system browser or secure browser tab, not an embedded web view. Generate code_verifier, code_challenge, state, and nonce on the device before opening authorization.
GET /api/auth/oauth2/authorize?client_id=CLIENT_ID&redirect_uri=https%3A%2F%2Fapp.example.com%2Fmobile%2Fcallback&response_type=code&scope=openid%20profile%20email&state=STATE&nonce=NONCE&code_challenge=CODE_CHALLENGE&code_challenge_method=S256
Store the code_verifier, state, and nonce in short-lived app storage until the callback is received.
2. Receive the App Link Callback
When the user completes login, verification, and consent, the system opens your app link callback with either:
https://app.example.com/mobile/callback?code=AUTHORIZATION_CODE&state=STATE
or OAuth error parameters such as:
https://app.example.com/mobile/callback?error=access_denied&state=STATE
Your app must:
- Verify the returned
state. - Read
codewhen present. - Load the matching
code_verifier. - Exchange the code at the token endpoint.
3. Exchange the Code
Send a form-encoded request from the app to the API token endpoint.
POST /api/auth/oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=AUTHORIZATION_CODE&code_verifier=CODE_VERIFIER&client_id=CLIENT_ID&redirect_uri=https%3A%2F%2Fapp.example.com%2Fmobile%2Fcallback
Admin-created mobile applications are Public PKCE clients. Do not send client_secret.
4. Store Tokens Securely
Store tokens in the platform's secure storage facility, such as Keychain on iOS or encrypted credential storage on Android. Avoid logging tokens or putting them in crash reports.
If a refresh token is issued, store it with the same protection as the access token. When refresh fails with invalid_grant, clear local tokens and restart login.
5. Call External APIs
Use bearer authentication for external APIs:
GET /api/external/me
Authorization: Bearer ACCESS_TOKEN
401 means the access token cannot be used. 403 means the token is valid but lacks a required scope, such as openid for /api/external/me.
Production Checklist
- Use HTTPS Universal Links or Android App Links for redirect handling.
- Register the exact HTTPS origin and redirect path.
- Use the system browser or secure browser tab.
- Generate PKCE values per login attempt.
- Validate
statebefore token exchange. - Store tokens only in secure platform storage.
- Clear tokens and restart login on
invalid_grantor repeated401responses.