Skip to Content
MuoCeon Docs
v1auth context

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.

ParameterTypeRequiredNotes
codestring✅Authorization code from the provider callback, 1–1024 chars
redirect_uristring✅Exactly the address used when the sign-in started
didstring✅Device id, 8–256 chars
code_verifierstring✅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"
}
FieldNotes
is_new_userWhether this callback created the account
Everything elseIdentical to the session token pair in Tokens

Behaviour

RuleNotes
Automatic account creationWhen no account matches, a new user is created with a random UUIDv7 username
Minimal dataOnly the provider's sub and display name are used; the email is ignored
PKCE requiredWithout it, an attacker can inject their own code into the victim's browser and sign the victim into the attacker's account
Error codesA 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

DimensionSign-in callback (this page)Binding (third-party identity)
AuthenticationAnonymousSession plus max_age=300
ResultIssues a session tokenAdds a credential to an existing account
Account creationMay create oneNever
didRequiredNot 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.

On this page