Public PKCE Login Quickstart
This quickstart shows the shortest path for a third-party application to sign in a user with Muhajir Studio and fetch the current user's scope-filtered profile.
Prerequisites
Before writing code, ask your Muhajir Studio admin for:
| Value | Description |
|---|---|
| API base URL | https://api.muhajirstudio.com/ — serves /api/auth/*, /api/public/*, and /api/external/*. |
| Login web base URL | https://login.muhajirstudio.com/ — serves login, signup, verification, and consent pages. |
| Admin web base URL | https://admin.muhajirstudio.com/ — where admins register and manage applications. |
client_id | The public client identifier generated in web-admin. |
| Registered redirect URI | An exact URI derived from the app's configured allowedWebOrigins and redirectPaths. |
| Allowed scopes | The scopes selected for this application in web-admin. |
Use these production URLs for live integrations. If you are integrating with sandbox or staging, use the matching service URLs provided by your Muhajir Studio contact when registering web origins, redirect paths, and callback URLs.
Admin-created applications are Public PKCE clients. Do not use a client_secret; no client secret is issued for these clients.
1. Generate PKCE and State Values
For each login attempt, generate and store these values in the user's browser session or your backend session:
| Value | Purpose |
|---|---|
code_verifier | Secret random value used later at the token endpoint. |
code_challenge | Base64url-encoded SHA-256 hash of code_verifier. |
state | CSRF protection value that must round-trip to your callback. |
nonce | Replay protection value to validate when using the id_token. |
Muhajir Studio requires code_challenge_method=S256; plain PKCE challenges are disabled.
2. Redirect to Authorization
Send the user's browser to the Muhajir Studio authorization endpoint at https://api.muhajirstudio.com/api/auth/oauth2/authorize:
GET /api/auth/oauth2/authorize?client_id=CLIENT_ID&redirect_uri=https%3A%2F%2Fapp.example.com%2Fauth%2Fcallback&response_type=code&scope=openid%20profile%20email&state=STATE&nonce=NONCE&code_challenge=CODE_CHALLENGE&code_challenge_method=S256
Required parameters:
| Parameter | Value |
|---|---|
client_id | Public client ID from web-admin. |
redirect_uri | Exact registered redirect URI. Muhajir Studio does not infer this from the browser Origin. |
response_type | Must be code. |
scope | Space-separated scopes. Keep this aligned with the app scopes configured by the admin. |
state | Your CSRF protection value. |
nonce | Recommended when validating the id_token. |
code_challenge | PKCE S256 challenge. |
code_challenge_method | Must be S256. |
Muhajir Studio validates that the redirect_uri is registered for the client. For dynamic applications, Muhajir Studio also constrains the effective authorization scopes to the application's configured scopes.
3. User Signs In, Verifies Email, and Consents
Muhajir Studio handles the user-facing flow in web-main:
- If the user is not authenticated, they are sent to the login or signup page.
- If the signed-in user's email is not verified, Muhajir Studio sends them to
/verify-emailbefore authorization completes. - After verification, Muhajir Studio resumes the original authorization request with the preserved OIDC parameters.
- Muhajir Studio shows a consent screen using registered application metadata from
GET /api/public/applications/{clientId}and shared scope descriptions. - The user approves or denies access.
For safety, the consent screen disables approval if registered application details cannot be loaded.
4. Handle the Callback
After approval, Muhajir Studio redirects the browser back to your registered redirect_uri with query parameters:
https://app.example.com/auth/callback?code=AUTHORIZATION_CODE&state=STATE
Your callback handler must:
- Confirm the returned
statematches the stored value. - Read the authorization
code. - Load the stored
code_verifierfor this login attempt. - Continue to token exchange.
If the user denies access or the request fails, Muhajir Studio can redirect back with OAuth error parameters instead of code.
5. Exchange the Code for Tokens
Send a form-encoded POST request to the 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%2Fauth%2Fcallback
For Public PKCE clients, do not send client_secret.
A successful response can include:
{
"access_token": "...",
"token_type": "Bearer",
"expires_in": 3600,
"id_token": "...",
"refresh_token": "...",
"scope": "openid profile email"
}
The refresh_token is present only when refresh-token behavior is available for the granted scopes/client. The offline_access scope is the scope intended for long-lived refresh-token based sessions where supported.
6. Fetch the Current User
Use the OIDC access token against the stable external API:
GET /api/external/me
Authorization: Bearer ACCESS_TOKEN
The token must include openid; otherwise Muhajir Studio returns 403 with missingScopes: ["openid"].
Example response with openid profile email:
{
"sub": "user-id",
"name": "Jane Doe",
"picture": null,
"email": "jane@example.com",
"emailVerified": true
}
If the token also has permissions, the response can include permissions with the user's effective Muhajir Studio permission keys.
Example Integration Shapes
Server-Rendered or Backend Web App
Use your backend to create the authorization URL, store state, nonce, and code_verifier, handle the callback, exchange the code, validate the id_token, and store tokens server-side. This is the preferred shape when your app already has a backend session.
React SPA
A browser SPA can use PKCE directly, but the browser origin must be registered as an allowedWebOrigin for the application. Muhajir Studio's third-party CORS support is route-scoped to /api/auth/oauth2/token and /api/external/* and does not use credentialed CORS.
Mobile App
Mobile apps should use Authorization Code with PKCE and a registered redirect URI appropriate for the platform, such as an app link or universal link. Store tokens in platform secure storage.
Common Quickstart Mistakes
- Sending a
client_secretfor an admin-created Public PKCE client. - Using
code_challenge_method=plaininstead ofS256. - Sending a
redirect_urithat is not exactly one of the derived registered redirect URIs. - Calling
/api/external/mewithout anAuthorization: Beareraccess token. - Expecting
/api/external/meto return fields for scopes that were not granted.