Single Sign-On

Let people sign in with an account they already have. Apple, Google and TikTok are set up as a service provider with no blueprint at all; mssgs mail and passkeys are entity and account settings; GitHub and Microsoft are blocks you wire yourself.

How provider sign-in works

Your app shows the provider's own button and sends what it gets back to the core. The core verifies it, finds the account or creates it, and answers with a session. There is no developer key on a pin and no blueprint to write: binding a service provider to the sign-in purpose is the whole setup.

  1. Create the service provider

    Add a service provider of the sign-in type with the provider's client ids, and bind it to its purpose.

  2. Show the provider's button

    Your app or page asks GET /auth/<provider>/config whether sign-in is on and which client ids to use.

  3. Hand the result to the core

    POST /auth/<provider> with what the provider returned. The answer is a session, or a 202 while a sign-up is held for its next step.

An existing account is never adopted by email Having a verified address at a provider does not hand over the RUAL account with that address, because linking on it would give the account to whoever controls the provider account. Sign in with Google has one exception, for a proven Gmail address, only when the entity turns link_verified_email on.

Sign in with Apple

A service provider of type apple_signin, bound to the apple_sign_in purpose. The app sends Apple's identity token; on the web, Sign in with Apple JS in popup mode hands the page an id_token and code, which the same endpoint accepts, with the Services ID listed beside the bundle ID.

RouteDoes
GET /auth/apple/configIs it on, which client ids, is a nonce required.
POST /auth/apple/nonceA one-time value for Apple's request.
POST /auth/appleIdentity token in, session out. 202 while a sign-up is held.
POST /auth/apple/signupThe next step of a held sign-up: email, resend, code, answer.
GET /auth/apple/statusSigned in: does this account use it.

Apple is the first factor, not both: where the account owes a second factor, it still does. Removing an account revokes its authorization at Apple when the core holds a refresh token, which App Store review requires of an app that offers account deletion. The older function_sso_apple_* blocks are deprecated in favour of this route.

Sign in with Google

A service provider of type google_signin, bound to google_sign_in. The routes are Apple's under /auth/google: /config, /nonce, the sign-in itself, /signup and /status. The body takes id_token, credential (what Google Identity Services hands a web callback) or identity_token.

  • List the web client id, on Android too. Android mints the token for the client your app names in setServerClientId. A provider listing only the Android client id refuses every Android sign-in with GOOGLE_AUDIENCE_MISMATCH, which is the first thing to check when a new app cannot sign in.
  • There is no client secret. Verification needs only Google's public keys, so the provider has no secret field.
  • Names come from the token. given_name and family_name fill a new account ahead of whatever the app sends.

Sign in with TikTok

A service provider of type tiktok_signin, bound to tiktok_sign_in. TikTok issues no identity token, so the core redeems an authorization code instead: POST /auth/tiktok with {code, redirect_uri, code_verifier}, plus /config, /signup and /status.

  • The redirect URI must be registered. It is checked against the provider's redirect_uris before TikTok is asked anything, or the answer is TIKTOK_REDIRECT_URI_NOT_ALLOWED. A loopback entry with a wildcard port (http://127.0.0.1:*/auth/tiktok/callback) serves a desktop app.
  • The account has no address. TikTok shares none, so an account is created from the TikTok identity with no email; display_name fills its first name on sign-up only.
  • Revoking access keeps the account. POST /tiktok/webhook on the entity's own host verifies TikTok's signature and marks an authorization.removed on the link rather than removing it, because the person would otherwise be locked out for good.

Sign in with mssgs mail

For an address mssgs mail serves, the passwordless login can offer the mssgs mail approval screen in place of an emailed code. Nothing changes until an entity sets idp_mssgsmail_enabled and idp_mssgsmail_client_secret, and only a client that sends sso: ["mssgsmail"] is ever offered it.

  1. POST auth/passwordless/request answers with an offer: { success, expires_in: 0, mssgsmail: { client_id, authorize_url } }.
  2. The client sends the person to mssgs mail to approve.
  3. POST auth/passwordless/verify with type mssgsmail redeems the returned code. The confirmed address must equal the identifier, and sign-in continues exactly as after an email code, second factor included.

A DNS failure or an unreachable provider mails the code as before, and force_email asks for the code regardless.

Passkeys

A passkey can be a second factor, or the whole sign-in for an account that switched it on. As a whole sign-in the ceremony requires user verification (Face ID, Touch ID, Windows Hello or a PIN), so the passkey plus the person counts as both factors; a key tapped without its PIN is refused and stays a second factor only.

RouteDoes
POST /auth/passkey/login/optionsStarts the ceremony: {entity} in, {publicKey, session} out.
POST /auth/passkey/loginFinishes it: {entity, session, credential} in, the login session out.

The switch belongs to the account: a person turns it on from the security page. The server writes that setting; no client route can set it.

GitHub and Microsoft

These are blocks rather than a provider: you build the redirect and the callback in your own blueprint, then decide what to do with the identity. The flow is the same for both.

  1. Send the person to the provider

    function_sso_github_get_auth_url or function_sso_microsoft_get_auth_url gives you the URL to redirect to.

  2. Verify the code on your callback

    function_sso_github_verify_code or function_sso_microsoft_verify_code exchanges the code for a token.

  3. Read who it is

    function_sso_github_get_user_info or function_sso_microsoft_get_user_info gives you the profile. Find or create your user from it.

Google has function_sso_google_get_user_info, function_sso_google_refresh_token and function_sso_google_revoke_token for existing flows; its auth URL and verify blocks are deprecated in favour of Sign in with Google above.

Next steps

Building a Login Page Passwordless login: email a code, verify it into a session token, and the page around it. Building User Authentication The sign-in flow, tokens, 2FA and the scope checks around them. Service Providers Set up the provider a sign-in reads its client ids and secrets from.

Frequently asked

Which sign-in providers does RUAL support?

Sign in with Apple, Google and TikTok are set up as a service provider with no blueprint at all, and mssgs mail is an offer on the passwordless routes. Passkeys work as a whole sign-in or a second factor. GitHub and Microsoft are blocks you wire into your own flow.

Why do Android sign-ins fail with GOOGLE_AUDIENCE_MISMATCH in RUAL?

The provider lists only the Android client id. Android mints the token for the web client your app names in setServerClientId, so the provider must list the web client id too.

Can Sign in with Apple take over an existing RUAL account with the same email?

No. An existing account is never adopted by email, because that would hand the account to whoever controls the Apple ID.