---
title: "Single Sign-On · RUAL Documentation"
description: "Sign in with Apple, Google, TikTok and mssgs mail through service providers, passkeys, and the GitHub and Microsoft SSO blocks."
canonical: https://docs.rual.nl/integrations/single-sign-on
language: en
---

# 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.

- [Sign in with Apple](#apple): Provider `apple_signin`, for apps and the web.

- [Sign in with Google](#google): Provider `google_signin`, for Android and the web.

- [Sign in with TikTok](#tiktok): Provider `tiktok_signin`, redeems a code.

- [Sign in with mssgs mail](#mssgs-mail): An offer on the passwordless routes, off by default.

- [Passkeys](#passkeys): A whole sign-in or a second factor, per account.

- [GitHub and Microsoft](#github-microsoft): OAuth blocks you wire into your own flow.

## 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.

- Create the service provider

Add a [service provider](https://docs.rual.nl/blueprints/service-providers) of the sign-in type with the provider's client ids, and bind it to its purpose.

- Show the provider's button

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

- Hand the result to the core

`POST /auth/ ` 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.

| Route | Does |
| --- | --- |
| `GET /auth/apple/config` | Is it on, which client ids, is a nonce required. |
| `POST /auth/apple/nonce` | A one-time value for Apple's request. |
| `POST /auth/apple` | Identity token in, session out. `202` while a sign-up is held. |
| `POST /auth/apple/signup` | The next step of a held sign-up: email, resend, code, answer. |
| `GET /auth/apple/status` | Signed 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](https://docs.rual.nl/tutorials/login-page) 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.

- `POST auth/passwordless/request` answers with an offer: `{ success, expires_in: 0, mssgsmail: { client_id, authorize_url } }`.

- The client sends the person to mssgs mail to approve.

- `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.

| Route | Does |
| --- | --- |
| `POST /auth/passkey/login/options` | Starts the ceremony: `{entity}` in, `{publicKey, session}` out. |
| `POST /auth/passkey/login` | Finishes 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.

- Send the person to the provider

[`function_sso_github_get_auth_url`](https://docs.rual.nl/block-types/users/function_sso_github_get_auth_url) or [`function_sso_microsoft_get_auth_url`](https://docs.rual.nl/block-types/users/function_sso_microsoft_get_auth_url) gives you the URL to redirect to.

- Verify the code on your callback

`function_sso_github_verify_code` or `function_sso_microsoft_verify_code` exchanges the code for a token.

- 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](https://docs.rual.nl/tutorials/login-page): Passwordless login: email a code, verify it into a session token, and the page around it.

- [Building User Authentication](https://docs.rual.nl/tutorials/user-authentication): The sign-in flow, tokens, 2FA and the scope checks around them.

- [Service Providers](https://docs.rual.nl/blueprints/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.
