Skip to content

Sign-in

Umpteenth has no passwords of its own, so you sign in through an OpenID Connect identity provider or with a GitHub account. Each way to sign in is a provider under auth.providers in config.yml, and the login page shows a button for each one.

  • If you run an identity provider such as Authentik, Keycloak or Zitadel, connect it through OpenID Connect.
  • If you don’t have one yet, install Pocket ID, a small OpenID Connect provider that runs in Docker next to Umpteenth, and connect it the same way.
  • If you’d rather not host an identity provider, sign in with GitHub.

You can offer several at once, as Several providers shows.

Every provider has an ID you pick from lowercase letters, digits and single hyphens, such as pocket-id or github. The ID is the provider’s key under auth.providers and the last part of its redirect URI, <app.url>/api/auth/callback/<id>, which you register with the provider. A provider with the ID github on https://umpteenth.example.com has the redirect URI https://umpteenth.example.com/api/auth/callback/github. Renaming the ID changes that URI, so register the new one along with it.

Umpteenth reads its providers at start, so restart it after a change:

Terminal window
docker compose restart umpteenth
  1. Register a client for Umpteenth in your identity provider.

    Setting Value
    Redirect URI <app.url>/api/auth/callback/<id>
    Scopes openid profile email groups, which Umpteenth requests on every sign-in
    Client type Confidential or public, since Umpteenth uses PKCE either way and sends the client secret when you set one

    Note the issuer URL, the client ID and, for a confidential client, the client secret.

  2. Add the provider to config.yml with the type oidc.

    config.yml
    auth:
    providers:
    pocket-id:
    type: oidc
    name: Pocket ID
    issuer: https://id.example.com
    client_id: umpteenth
    client_secret: "<client secret>"

    name labels the button, which reads Sign in with Pocket ID here. Leave client_secret empty for a public client.

Umpteenth fetches the issuer’s configuration from inside its container, so the issuer URL has to work there as well as in your browser. An issuer at http://localhost:1411 works in the browser and fails in the container, where localhost is the container itself (Troubleshooting).

Everyone your identity provider admits to the client can sign in. To narrow that down, list groups in the provider’s allowed_groups, such as allowed_groups: [umpteenth-admins], and have your identity provider put the groups claim into the ID token. Umpteenth then admits members of at least one listed group. It compares the names with the claim as written, case included, so Admins doesn’t match admins.

A github provider signs you in with an account on github.com through a GitHub OAuth app. It talks to github.com only, so accounts on GitHub Enterprise Server can’t use it.

  1. On GitHub, open Settings → Developer settings → OAuth Apps and click New OAuth App. To register the app under an organization, open Developer settings → OAuth Apps in the organization’s settings instead.

  2. Fill in the form and click Register application.

    Field Value
    Application name The name GitHub shows when it asks you to authorize the app, such as Umpteenth
    Homepage URL app.url, such as https://umpteenth.example.com
    Authorization callback URL <app.url>/api/auth/callback/github, with the provider’s ID at the end

    Leave Enable Device Flow off, since Umpteenth doesn’t use it.

  3. Click Generate a new client secret, and copy the secret and the Client ID. GitHub shows the secret only once.

  4. Add the provider to config.yml with the type github, and list who may sign in.

    config.yml
    auth:
    providers:
    github:
    type: github
    name: GitHub
    client_id: "<client ID>"
    client_secret: "<client secret>"
    allowed_users: [octocat]
    allowed_organizations: [acme]

Any GitHub account can authorize an OAuth app, so a github provider needs allowed_users, allowed_organizations or both, and Umpteenth refuses to start with neither. allowed_users lists GitHub usernames, which Umpteenth compares ignoring case. allowed_organizations admits the active members of the listed organizations, so a pending invitation isn’t enough. Everyone else lands back on the login page with “Your account is not allowed to use Umpteenth”.

Umpteenth asks GitHub for the user:email scope, to read the primary email address when the profile shows none, and for read:org when you list organizations. If an organization restricts access for OAuth apps, an owner has to approve the app on GitHub, or GitHub hides the membership and Umpteenth turns the organization’s members away.

Umpteenth keys a GitHub user by the numeric account ID, so a renamed account keeps its Umpteenth user. allowed_users matches the current username, so update the list after a rename.

An OAuth app takes a single callback URL, so each Umpteenth instance with its own app.url, such as staging and production, needs an OAuth app of its own.

Add a block under auth.providers for each way to sign in, and mark one as primary:

config.yml
auth:
providers:
pocket-id:
type: oidc
name: Pocket ID
issuer: https://id.example.com
client_id: umpteenth
client_secret: "<client secret>"
primary: true
github:
type: github
name: GitHub
client_id: "<client ID>"
client_secret: "<client secret>"
allowed_organizations: [acme]

The primary provider’s button is the large one at the top of the login page, and the others follow under an or divider as outline buttons, sorted by name. A lone provider gets the large button without primary, while several providers without a primary one all get outline buttons. With more than one provider, a Last used badge marks the one this browser signed in with last.

A button shows the provider’s icon, an http:// or https:// URL or a data:image/ URI. Without one, a github provider shows the GitHub mark and an oidc provider a generic sign-in icon.

Umpteenth tells users apart by the account they sign in with, so a person who signs in through Pocket ID and through GitHub becomes two users.

Instance admins see every user and workspace of the instance and can deactivate users, as Workspaces describes. You name them in the options of the provider they sign in with:

config.yml
auth:
providers:
pocket-id:
type: oidc
name: Pocket ID
issuer: https://id.example.com
client_id: umpteenth
admin_groups: [umpteenth-admins]
github:
type: github
name: GitHub
client_id: "<client ID>"
client_secret: "<client secret>"
allowed_organizations: [acme]
admin_users: [octocat]

An oidc provider takes admin_groups, which Umpteenth compares with the groups claim the same way as allowed_groups. A github provider takes admin_users and admin_organizations, matched like its allow lists. Admins get in even when the allow lists leave them out, so a github provider that lists only admins is valid too.

Umpteenth checks the lists at every sign-in, so someone you take out of an admin group keeps the admin rights until they sign in again.

A provider’s options take environment variables with the ID in upper case and its hyphens turned into underscores, such as AUTH_PROVIDERS_POCKET_ID_ISSUER. They override single options of a provider from config.yml, and they can define a whole provider on their own:

docker-compose.yml
services:
umpteenth:
environment:
AUTH_PROVIDERS_GITHUB_TYPE: github
AUTH_PROVIDERS_GITHUB_NAME: GitHub
AUTH_PROVIDERS_GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID}
AUTH_PROVIDERS_GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET}
AUTH_PROVIDERS_GITHUB_ALLOWED_ORGANIZATIONS: acme

Configuration lists every provider option with its default, and its section on environment variables covers .env files and reading secrets from files with _FILE.