Third-party callback
POST /v1/auth/provider/:provider/callback — exchanging a provider's authorization code for a session token.
The landing point of third-party sign-in. It exchanges the authorization code from the provider callback for a session token of this platform, creating an account when the identity is not registered yet.
Request
POST /v1/auth/provider/:provider/callback, where provider is github or microsoft.
| Parameter | Type | Required | Notes |
|---|---|---|---|
code | string | ✅ | Authorization code from the provider callback, 1–1024 chars |
redirect_uri | string | ✅ | Exactly the address used when the sign-in started |
did | string | ✅ | Device id, 8–256 chars |
code_verifier | string | ✅ | Raw PKCE value, 43–128 chars |
{
"success": true,
"message": "Signed in",
"is_new_user": false,
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 900,
"acr": "urn:muoceon:acr:aal1",
"auth_time": "2026-11-14T08:31:12.000Z"
}| Field | Notes |
|---|---|
is_new_user | Whether this callback created the account |
| Everything else | Identical to the session token pair in Tokens |
Behaviour
| Rule | Notes |
|---|---|
| Automatic account creation | When no account matches, a new user is created with a random UUIDv7 username |
| Minimal data | Only the provider's sub and display name are used; the email is ignored |
| PKCE required | Without it, an attacker can inject their own code into the victim's browser and sign the victim into the attacker's account |
| Error codes | A rejected code returns AUTH_PROVIDER_AUTHORIZATION_FAILED (400); an unreachable provider returns AUTH_PROVIDER_UNAVAILABLE (502) |
This endpoint never returns 401
401 means "the caller's token is invalid". This endpoint has no Bearer token, so it never uses 401:
a rejected code is 400, a dead provider is 502. Mixing them up sends clients off to refresh a token that does not exist.
How it differs from binding
| Dimension | Sign-in callback (this page) | Binding (third-party identity) |
|---|---|---|
| Authentication | Anonymous | Session plus max_age=300 |
| Result | Issues a session token | Adds a credential to an existing account |
| Account creation | May create one | Never |
did | Required | Not accepted |
They are kept apart on purpose: merged into one endpoint, a missing or forged flag would turn a sign-in-only endpoint into something that can attach credentials to any account.
Related
- Provider directory: Credential management
- Full integration flow: Authorization code flow