Sign-in methods
Choose how your app's users sign in — email and password, email link, Runlot, your own GitHub or Google app, or any OpenID Connect provider.
Every way in is one method in the same list. The dashboard's Sign-in & access tab shows them all under App users, and runlot auth status prints the same list.
| Method | Turn on or off |
|---|---|
| Email and password | runlot auth set password on|off |
| Email link | runlot auth set magic-link on|off |
| Runlot | runlot auth provider runlot on|off |
| Your own GitHub or Google app | runlot auth provider set github|google …, runlot auth provider rm … |
| Any OIDC provider | runlot auth provider oidc add <id> …, runlot auth provider oidc rm <id> |
Changing a provider requires the admin role.
409 last_method. If your app should have no sign-in at all, turn login off instead.Email and password, email link
Both are on by default.
runlot auth set password off # hide the password form
runlot auth set magic-link off # hide the email linkWith password sign-in off, the password routes answer 404 method_disabled and the default sign-in page has no form. Existing password hashes are kept, so turning it back on restores those accounts. Verification mail still goes out with both off, because an app that signs in only with social providers still verifies addresses.
Runlot
runlot auth provider runlot onYour sign-in page gets one Continue with Runlot button. It leads to a Runlot page that shows your app's name and logo and offers email and password, Google and GitHub. The person comes back to your app signed in. There is no client ID, no secret and no callback URL to register, and adding a custom domain changes nothing.
The user is stored in your app with the identity provider runlot. Its subject is a pairwise ID: the same person gets a different subject in each app, so two apps cannot match their users by it. The email is included only when Runlot has verified it.
If Runlot sign-in is not offered on your installation, the command answers 409 runlot_unavailable.
runlot auth provider runlot offYour own GitHub or Google app
Register your own OAuth app when you want your app's name on the provider's consent screen, a quota of your own, or a GitHub Enterprise Server.
runlot auth provider set github --client-id <id> --client-secret <secret>
runlot auth provider set google --client-id <id> --client-secret <secret>If you omit --client-secret, the terminal prompts you for the value.
On a self-hosted installation whose GitHub is a GitHub Enterprise Server, add --issuer https://github.acme.example to the github line. The option is for github only, and the same field is in the dashboard.
Any OpenID Connect provider
Any provider that speaks OpenID Connect can be added under an ID of your choice: LINE, Apple, Microsoft Entra, Okta, Keycloak, your company's IdP.
runlot auth provider oidc add <id> --issuer https://idp.example.com \
--client-id <client-id> [--name "Example"] [--icon https://…/icon.svg] [--scopes "openid email profile"]
# the client secret is prompted
runlot auth provider oidc rm <id><id>is a short name of your own: a lowercase letter, then lowercase letters, digits or hyphens, 2 to 31 characters.github,googleandrunlotare taken.--issuermust behttps. Runlot reads<issuer>/.well-known/openid-configurationwhen you save. If that fails, the save is refused with400 oidc_discovery_failedand the provider's answer.--scopesdefaults toopenid email profile.
The ID token is verified on every sign-in: signature, issuer, audience, expiry and nonce. A provider that does not say an email is verified (email_verified) creates an unverified user, which is never linked to an existing account by email.
In the dashboard, Add an OIDC provider has the same fields and shows the callback URL before you save.
Example: Kakao
Kakao Login speaks OpenID Connect once you turn it on.
- In the Kakao Developers console, open your app, go to Kakao Login, and turn on OpenID Connect.
- Register the callback URL
https://<your-domain>/__runlot/auth/callback/kakaoas a Redirect URI. - Add the provider. The client ID is the app's REST API key, and the secret is the Client Secret from the security settings.
runlot auth provider oidc add kakao --issuer https://kauth.kakao.com \
--client-id <REST API key> --name "Kakao"Callback URL
Your own GitHub, Google and OIDC apps need the following URL registered in the provider's console, once for every host your project answers on. Runlot needs none.
https://<your-domain>/__runlot/auth/callback/<id>runlot auth status prints the exact list. When you add a custom domain, add its callback URL in the provider console too; sign-in fails on any host you miss, and the error is shown only at the provider.
Sign-up and email settings apply
allowSignup and requireVerifiedEmail apply to every method the same way. With sign-ups off, a new account from any provider cannot create a user; with verified email required, a provider that does not vouch for the address does not get a session.
Using it from your own login screen
Methods you turn on appear as buttons on the default sign-in page. A sign-in page of your own should ask which ones are on, rather than hard-code buttons:
import { providers, signInUrl } from "@runlot/auth/client";
for (const p of await providers()) {
// p.id is "runlot", "github", "google" or your OIDC id; OIDC entries carry name and icon
render(<a href={signInUrl(p.id, { next: "/app" })}>Continue with {p.name ?? p.id}</a>);
}signInUrl("github", { next: "/app" }) links to /__runlot/auth/sign-in/github?next=%2Fapp. If next is an external URL or starts with //, it is ignored for security.
Linking accounts with the same email
If password sign-in and a provider use the same verified email address, they are linked to a single user account. You can see which providers a user has with user.providers.
const user = await env.auth.user(request);
user.providers; // ["password", "github"]Removing a provider
runlot auth provider rm githubUsers who only signed in with the provider you removed can regain access by resetting their password, while password sign-in is on.