Skip to main content

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.

ServiceProduction URLUsed for
APIhttps://api.muhajirstudio.com/Authorization, token exchange, refresh, and external APIs.
Main webhttps://login.muhajirstudio.com/Hosted login, signup, verification, and consent.
Admin webhttps://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:

FieldExampleNotes
Allowed web originhttps://app.example.comHTTPS origin controlled by your app/team.
Redirect path/mobile/callbackPath opened by your Universal Link or App Link handler.
Redirect URIhttps://app.example.com/mobile/callbackDerived from origin + path.
Scopesopenid profile email offline_accessInclude 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.

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:

  1. Verify the returned state.
  2. Read code when present.
  3. Load the matching code_verifier.
  4. 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 state before token exchange.
  • Store tokens only in secure platform storage.
  • Clear tokens and restart login on invalid_grant or repeated 401 responses.