Skip to content
runlot

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.

MethodTurn on or off
Email and passwordrunlot auth set password on|off
Email linkrunlot auth set magic-link on|off
Runlotrunlot auth provider runlot on|off
Your own GitHub or Google apprunlot auth provider set github|google …, runlot auth provider rm …
Any OIDC providerrunlot auth provider oidc add <id> …, runlot auth provider oidc rm <id>

Changing a provider requires the admin role.

At least one method has to stay on. A change that would leave none is refused with 409 last_method. If your app should have no sign-in at all, turn login off instead.

Both are on by default.

runlot auth set password off      # hide the password form
runlot auth set magic-link off    # hide the email link

With 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 on

Your 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 off

Your 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, google and runlot are taken.
  • --issuer must be https. Runlot reads <issuer>/.well-known/openid-configuration when you save. If that fails, the save is refused with 400 oidc_discovery_failed and the provider's answer.
  • --scopes defaults to openid 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.

  1. In the Kakao Developers console, open your app, go to Kakao Login, and turn on OpenID Connect.
  2. Register the callback URL https://<your-domain>/__runlot/auth/callback/kakao as a Redirect URI.
  3. 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 github

Users who only signed in with the provider you removed can regain access by resetting their password, while password sign-in is on.

On this page