OAuth
Google or GitHub can supply the identity used for login, while mesgd retains control of the account session and its authenticator requirement. A successful provider login is therefore an intermediate step: the person must still enter a mesgd authenticator code before receiving a session. Configure oauth_providers to enable this flow; see Configuration.
Google uses OpenID Connect. mesgd accepts only RS256, pins Google's JWKS endpoint, and checks issuer, audience, authorized party, signature, expiry, issue and not-before times, nonce, and the stable subject. GitHub does not issue an ID token. mesgd exchanges the code and checks the access token against GitHub's user API. The numeric GitHub user id is the stable subject.
A verified email may be stored as contact information. mesgd does not merge two accounts because two providers returned the same email.
Browser sign-in
GET /auth/oauth/providerslists the providers you configured and eachstart_path.- Open
GET /auth/oauth/PROVIDER/start.POSTthat path when you wantauthorization_urlwithout a redirect. mesgd sets a cookie that binds the browser to this flow. The URL carries a one-usestateand a PKCE S256 challenge. Google also receives a nonce. - The provider redirects to
/auth/oauth/PROVIDER/callback. mesgd checks the browser, state, provider, code, and identity, then sets a short-lived result cookie. GET /auth/oauth/pendingreturnsoauth_token,provider,action, and an optional user or verified email. The proof lasts five minutes and allows five attempts.- For
action=login,POST /auth/oauth/completewithoauth_tokenandotp. Success returns the usual mesgd bearer session. The proof is used up. - For
action=register,POST /auth/oauth/registerwithoauth_token, an optionaluser, a contact email when the provider has no verified email, and an optional backup password. The result is a pending authenticator enrollment. Confirm with/auth/signup/confirmbefore any session or provider link exists.
A native client can ask for JSON instead of a redirect by using the explicit Erlang undefined completion destination. Flow state is in memory. If mesgd restarts, the person starts again. In a cluster, keep one browser's /auth/oauth/ requests on one node until the flow finishes.
Google ID token from your app
GETorPOST /auth/oauth/google/challenge. Keep the cookies.- Request a Google ID token with the returned
client_idandnonce. POST /auth/oauth/google/tokenwithchallenge_tokenandid_token, and the same cookies.- Finish with
otpthrough/auth/oauth/complete, the same way as the browser flow.
mesgd rejects an ID token that was not issued for this challenge nonce. A provider's own MFA claim does not replace the mesgd authenticator.
Link and unlink
POST /auth/oauth/PROVIDER/link with a mesgd bearer token starts a link for the signed-in user. After the provider callback, finish the proof with that same session and a fresh authenticator code.
GET /auth/oauth/accounts lists linked providers and stable subjects.
DELETE /auth/oauth/accounts/PROVIDER with JSON {"otp":"123456"} removes that link. mesgd refuses to remove the last way to sign in. A local password or another provider has to remain.
An account can link one identity per provider. The provider and subject pair becomes reserved when enrollment is confirmed, so two pending signups can refer to the same subject until one completes confirmation.
Add another provider
A module that implements mesgd_oauth_provider can be named in the provider config. It supplies authorization_url/2 and exchange/4 and returns {ok, #{provider => <<"name">>, subject => <<"stable-id">>}}. Include email only when the provider has verified it. Implement verify_token/4 when you want a direct token challenge, and do the provider's signature and claim checks there.