Sign-in methods reference

The sign-in methods of a TaleArt install: what each is, what an admin configures for an identity provider, the environment variables, the endpoints, the error codes and the security properties. For the steps to set them up, see the Sign-in methods guide.

Methods

Sign-in methods
Method idLabelKindTurned onWhat is stored
passkeyPasskeypasskeyOn from a fresh install.A passkey per device, with its public key; the private key stays on the device or in a password manager.
passwordUsername and passwordpasswordOff until an admin turns it on.A scrypt hash of the password, and the lower-case username.
googleGoogle (a preset)googleAdded and turned on by an admin.Client ID and scopes in plain text; the client secret encrypted.
appleApple (a preset)appleAdded and turned on by an admin.Client ID, Team ID and Key ID in plain text; the .p8 private key encrypted.
oidc:<slug>A generic OpenID Connect provideroidcAdded and turned on by an admin, under a slug the admin picks.Issuer, client ID and scopes in plain text; the client secret encrypted.

A fresh install has the passkey on and the password off. Each admin can turn the passkey and the password on or off in Settings > Sign-in methods. At least one method must stay on, and every admin must keep one usable method.

Provider settings

An admin adds a provider in Settings > Sign-in methods > Add a provider. The kind is Google, Apple or Generic OpenID Connect. The redirect URI to register at the provider is PUBLIC_API_URL/api/v1/auth/callback/<slug>, for example https://api.example.com/api/v1/auth/callback/google, and it appears in the drawer once the provider is saved. Secrets are write-only: the API never returns them, only whether one is set.

Provider settings, by kind
FieldKindsRequiredWhere it is stored
Slug (the URL name, e.g. company-sso)Generic OpenID ConnectYes, lower-case letters, digits and hyphens, up to 40Plain (the provider key)
Button name (display name)AllYes, up to 80 charactersPlain
Issuer URL (issuer)Generic OpenID ConnectYes, https (http only for localhost outside production)Plain
Client ID (clientId)AllYes, up to 255 charactersPlain
Scopes (scopes)Generic OpenID Connect, GoogleNo; default openid email profile; must include openid; up to 200 charactersPlain
Team ID (teamId)AppleYes, 10 letters and digitsPlain
Key ID (keyId)AppleYes, 10 letters and digitsPlain
Client secret, or the Apple .p8 private key as PEM (secret)AllYes, to make the provider usable; up to 8,192 charactersEncrypted (AES-256-GCM, TALEART_SECRET_KEY); never returned by the API

Environment variables

Environment variables of the API for sign-in
VariableRequiredValueEffect
TALEART_SECRET_KEYTo save any provider secretBase64 of 32 random bytes, e.g. openssl rand -base64 32.Encrypts provider secrets. Without a valid key the API still runs but refuses to save a secret (503 secret_key_missing).
TALEART_SETUP_PASSWORDNoOnly the literal true enables it. Default off.On an empty install, the first admin may set up with a username and password.
PUBLIC_API_URLSet it for any real installThe public address of the API, default http://localhost:3333.The redirect URI is PUBLIC_API_URL plus /api/v1/auth/callback/<slug>.
RP_ORIGINSet it for any real installThe dashboard origin, default http://localhost:4200.Where the dashboard lives; passkeys and the cookie Secure flag follow it (Secure when it starts with https:).
RP_IDSet it for any real installThe dashboard host name, default localhost.Passkeys are bound to this host name.
NODE_ENVSet to production for a real installAny value; production turns something off.Outside production, a provider issuer may be plain http on localhost. In production it must be https.

Endpoints

The Sign-in methods tag of the API reference. Every path is listed here.

Sign-in methods endpoints
MethodPathWho may callPurpose
GET/auth/account/methodsA signed-in user (session cookie)The user's passkeys, password username and linked provider identities.
PUT/auth/account/passwordA signed-in userSet a password, or change it (the current password is needed when one is set).
DELETE/auth/account/passwordA signed-in userRemove the password, if another method stays usable.
DELETE/auth/account/passkeys/{passkeyId}A signed-in userRemove one of the user's passkeys, if another method stays usable.
DELETE/auth/account/identities/{identityId}A signed-in userUnlink one of the user's provider identities, if another method stays usable.
GET/auth/settingsAn adminWhich methods are on, and whether the server has the secret key.
PUT/auth/settingsAn adminTurn the passkey and password methods on or off.
GET/auth/providersAn adminThe providers, with usable, hasSecret and the redirect URI. Never a secret.
PUT/auth/providers/{slug}An adminAdd a provider, or replace its settings; send or remove its secret.
DELETE/auth/providers/{slug}An adminRemove a provider and its secret.
POST/auth/users/{userId}/password-resetAn adminIssue a one-time reset link for a user (shown once).
GET/auth/providers/{slug}/startAnyone, without a session (purpose link needs a session)Start a sign-in, setup, invitation or link with a provider; redirects to the provider.
GET/auth/callback/{slug}Anyone; the taleart_oauth cookie and the state must matchThe redirect back from a provider.
POST/auth/callback/{slug}Anyone; the same checks as the GET callbackThe form-posted redirect back from Apple (response_mode=form_post).
POST/auth/providers/{slug}/testAn adminRun the provider's discovery and report the issuer and endpoints. The secret is not used.

None of these accept an API token: a request with an Authorization header is refused. Admin endpoints need an admin session.

Error codes

Every error answers the standard body, with a code field such as {"error":{"code":"sign_in_failed"}}. The codes of sign-in are:

Sign-in error codes
CodeMeaning
sign_in_failedA sign-in was refused. The same answer for an unknown user, a wrong password, a method that is off, or a provider that is not usable.
password_rejectedThe password does not meet the policy (12 to 128 characters, not the username or the email's local part, not a common password).
username_takenThe username is already in use.
password_incorrectThe current password is wrong when changing a password.
password_reset_invalidThe reset link is unknown, used, or past its 24 hours.
sign_in_method_disabledThe method is turned off.
last_sign_in_methodThe change would leave no method usable: TaleArt will not remove the last one.
sign_in_lockoutThe change would leave an admin with no way to sign in.
secret_key_missingThe server has no valid TALEART_SECRET_KEY, so a provider secret cannot be saved.
provider_not_foundNo provider has that slug.
identity_in_useThe provider identity is already linked to another account.
email_not_verifiedThe provider did not verify the email, so the identity cannot redeem an invitation.
email_mismatchThe provider's verified email is not the email typed on the invitation page.
session_requiredA link needs a signed-in user.
discovery_failedThe discovery document could not be read, or its issuer is not the configured one.
provider_unavailableThe provider's keys or endpoints could not be read.
invitation_invalidThe invitation is unknown, used, or past its 7 days.
setup_closedThe first admin already exists, so setup is closed.
passkey_failedThe passkey ceremony was refused or did not check out.
rate_limitedToo many attempts from this address. Wait, then try again .
not_foundThe item does not exist, or it is another user's.

Security properties

  • Stored as hashes or encrypted: passwords as scrypt hashes; session and reset tokens as SHA-256 hashes; provider secrets as AES-256-GCM ciphertext. The API never returns a password, a reset token or a provider secret.
  • Passwords: 12 to 128 characters, with no composition rules; not the username or the email's local part; not one of about 100 common passwords. scrypt with N=2^15, r=8, p=1, a 64-byte key and a random 16-byte salt. Compared in constant time; an unknown username is checked against a dummy hash, so timing does not reveal it.
  • Throttling: 5 failed password sign-ins for a username wait 30 seconds, doubling per failure, up to 15 minutes; failures are forgotten after an hour. Per address: 10 password sign-ins in a burst, then 10 a minute. Provider sign-ins: 20 in a burst, then 20 a minute. The throttle is in memory, per API process.
  • Session revocation: a password change or a reset ends the user's other sessions; the session making the change stays signed in. A reset ends every session and starts a new one.
  • Provider flows use PKCE (S256), a state and a nonce of 32 random bytes each, stored server-side and bound to the browser by the taleart_oauth cookie (http-only, SameSite=Lax, path /api/v1/auth, 10 minutes). Each challenge is single use.
  • ID tokens: only RS256, ES256 and PS256 signatures are accepted (never none or HS*); issuer, audience, expiry and nonce are checked, with 60 seconds of clock skew.
  • Discovery: the document's issuer must equal the configured issuer exactly; endpoints must be https (plain http only on localhost outside production); 5 second timeout; 256 KiB size cap; redirects are refused. The JWKS is cached for 5 minutes.
  • Apple: the client secret is an ES256 JWT signed with the .p8 key, with the key ID in its header, created for each sign-in with a 5-minute lifetime and never stored.
  • Email: a provider email is used only when the provider verified it. A provider identity never creates an account by itself, and an account is never matched by email alone. An identity attaches to a user only when redeeming an invitation (the verified email equals the email typed on the invitation page), in the first-admin setup, or when a signed-in user links it.
  • Registration is by invitation only, plus the first admin on an empty install. There is no open sign-up and no domain auto-join.
  • Password recovery is an admin-issued link: 32 random bytes, valid once for 24 hours, a new link replaces the unused earlier ones, and it is shown once. TaleArt sends no email.
  • Sessions: 7 days, a random token in an http-only cookie (taleart_session, SameSite=Strict, Secure on https). API tokens are unchanged and are not used for sign-in.

API tokens are unchanged: a token still calls the Management API as its user, and sign-in methods are never reached with one. See API tokens.