Taifa Identity. Docs
OpenAPI Developers

Get started

Quick start

Development6 min read View .md

Quick start

Run the owned issuer in an isolated local environment and test an OIDC authorization code flow. This exercise produces a synthetic account with no Institution or product roles. It cannot serve as a production application registration.

Integration readiness: This is an isolated development checkpoint. For application integration, start with web sign-in, native sign-in, and client registration. The runnable fixture below exercises only the existing local portal issuer; it does not create an approved product client or enable production sign-in.

1. Verify the local toolchain

Start in the Taifa Identity repository root. Keep TAIFA_IDENTITY_ROOT in the same shell for the later command blocks. Use Go 1.27.1 and a disposable PostgreSQL database on loopback. The database name must include test, scratch, dev, or preview. The issuer refuses any other database in development. Set AUTH_TEST_DATABASE_URL to a disposable database URL for the database integration tests. Keep all secrets outside source control.

TAIFA_IDENTITY_ROOT="$PWD"
cd "$TAIFA_IDENTITY_ROOT/services/auth"
go mod verify
go vet ./...
go test -race ./...
go build ./...

The test suite uses AUTH_TEST_DATABASE_URL when provided. Database tests use unique disposable schemas. The tests cover PKCE, one-use codes, refresh rotation, expired authority leases, and challenge refusal. They do not require a live application client.

2. Create a disposable issuer

Apply the numbered migrations from services/auth/migrations/001_init.sql through 014_owned_client_management_readback.sql in order to that disposable database. Migrations 005 and 006 supply the registry, 007 supports enrollment, 008 supports logout, 009 supports durable activation retries, 010 supports private admission mail replay protection, and 011 supports central browser SSO. Migrations 012 and 013 add writer and custody schema foundations. Migration 014 scopes authenticated Management readback and its replay records; it does not register a client or grant access. Reviewed client installation remains unfinished, and this exercise does not enable the separate custody daemon. Holder setup is optional and requires separate signed authority configuration. This synthetic sign-in exercise does not provision a reviewed holder. Set these issuer variables through a private process environment:

VariableLocal value or purpose
AUTH_DEV_INSECURE_LOOPBACK1; permits only the disposable loopback mode.
AUTH_CLIENT_REGISTRY_MODEfixture; allows only validated local fixture registrations in development.
AUTH_DATABASE_URLURL of the disposable PostgreSQL database on an explicit loopback IP.
AUTH_ISSUERExact HTTPS issuer URL served by a trusted local TLS proxy.
AUTH_LOGIN_URLPortal’s exact HTTPS /signin URL.
AUTH_CLIENT_REDIRECT_URLPortal’s exact HTTPS /auth/callback URL.
AUTH_CLIENT_IDtaifa-identity-portal.
AUTH_CLIENT_SECRETIndependent random secret of at least 32 bytes, shared with the portal as OIDC_CLIENT_SECRET.
AUTH_BFF_KEYIndependent random secret of at least 32 bytes, shared only with the portal BFF.
AUTH_PUBLIC_LISTEN, AUTH_INTERNAL_LISTENDifferent explicit loopback IP listeners. Keep the internal listener private.
AUTH_TOTP_KEY_B64, AUTH_CRYPTO_KEY_B64Distinct standard Base64 encodings of independent 32-byte keys.
AUTH_SIGNING_KEY_FILE, AUTH_SIGNING_KEY_IDOwner-only RSA private key file, at least 3072 bits, and its public JWKS key ID.

Optional passkeys require all three of AUTH_PASSKEY_RP_ID, AUTH_PASSKEY_ORIGIN, and AUTH_PASSKEY_KEY_B64. The key must be a third independent 32-byte value. An authority lease receiver requires a separately reviewed subject mapping and the AUTH_ELIGIBILITY_* configuration in the service README; synthetic accounts do not use that receiver.

3. Register the disposable portal fixture

In fixture mode, the current issuer validates local fixture registrations stored in auth_clients; environment variables alone do not register a client. This local-only fixture creates the portal registration with the SHA-256 digest of its private client secret and the exact configured callback. It refuses production databases and does not update an existing registration. Run it from services/management, whose locked environment supplies psycopg. These fixture registrations are not reviewed registrations, and migration 012’s writer schema is not a runnable registration writer.

cd "$TAIFA_IDENTITY_ROOT/services/management"
uv run --locked python - <<'PY'
import hashlib
import ipaddress
import os
from urllib.parse import unquote, urlsplit
import psycopg

url = os.environ["AUTH_DATABASE_URL"]
parsed = urlsplit(url)
name = unquote(parsed.path.lstrip("/")).lower()
try:
    loopback_host = ipaddress.ip_address(parsed.hostname).is_loopback
except ValueError:
    loopback_host = False
if (os.environ.get("AUTH_DEV_INSECURE_LOOPBACK") != "1"
        or not loopback_host
        or not any(word in name for word in ("test", "scratch", "dev", "preview"))):
    raise SystemExit("A disposable loopback database is required")
secret = os.environ["AUTH_CLIENT_SECRET"].encode()
if not 32 <= len(secret) <= 1024:
    raise SystemExit("An independent high-entropy client secret is required")
with psycopg.connect(url) as connection:
    connection.execute(
        "INSERT INTO auth_clients "
        "(id,secret_hash,redirect_uris,resource_audiences,refresh_allowed,"
        "management_access,review_id,enabled) "
        "VALUES (%s,%s,%s,%s,%s,%s,%s,%s) ON CONFLICT (id) DO NOTHING",
        ("taifa-identity-portal", hashlib.sha256(secret).digest(),
         [os.environ["AUTH_CLIENT_REDIRECT_URL"]], ["taifa-management"],
         True, True, "disposable-local-exercise", True),
    )
PY

Keep the fixture database and all secrets private. Startup rejects missing, disabled, malformed or mismatched portal registrations. The registration gives the synthetic person no management role. Start the issuer:

cd "$TAIFA_IDENTITY_ROOT/services/auth"
go run ./cmd/authd

A local TLS proxy may expose the configured HTTPS issuer while forwarding to the loopback public listener. Do not expose the private challenge listener. The issuer publishes discovery, /authorize, /oauth/token, and /keys; the browser challenge API is private to the portal BFF.

4. Create one synthetic account

Set AUTH_BOOTSTRAP_USERNAME and AUTH_BOOTSTRAP_OUTPUT to a path in a private 0700 directory. With the same disposable database and TOTP encryption key, run:

cd "$TAIFA_IDENTITY_ROOT/services/auth"
go run ./cmd/auth-bootstrap

The output file is 0600 and contains the generated subject, password, and TOTP seed. Use it only for the local exercise. The account’s lease lasts one hour and it has no management privilege.

5. Exercise the browser flow

Apply apps/portal/migrations/001_sessions.sql to a separate disposable portal database, or set PORTAL_DATABASE_URL and run npm run migrate from apps/portal. Install the locked portal dependencies with npm ci. The portal needs PORTAL_ORIGIN (trusted HTTPS origin), PORTAL_DATABASE_URL, PORTAL_SESSION_KEY (standard Base64 encoding of exactly 32 cryptographically random bytes), OIDC_ISSUER (equal to AUTH_ISSUER), OIDC_CLIENT_ID=taifa-identity-portal, OIDC_CLIENT_SECRET (equal to AUTH_CLIENT_SECRET), AUTH_ISSUER_URL (equal to OIDC_ISSUER), AUTH_INTERNAL_URL (the private issuer listener), AUTH_BFF_KEY, AUTH_ENGINE_MODE=custom, and AUTH_DEV_INSECURE_LOOPBACK=1. Trust the local TLS certificate in the browser and backend. Keep the private listener off public ingress.

cd "$TAIFA_IDENTITY_ROOT/apps/portal"
npm ci
npm run migrate
npm run check
npm run build
npm run dev

Serve the portal development process through the trusted HTTPS origin named by PORTAL_ORIGIN, then begin at PORTAL_ORIGIN/auth/login. The BFF maintains the login transaction, an HttpOnly challenge cookie, and CSRF protection. Password plus TOTP or a configured passkey completes the private challenge. The browser follows the issuer callback URL, and the BFF redeems the code with the original S256 verifier.

Inspect the resulting verified iss and sub in the session and the account screen. The synthetic subject has no product access or management roles; protected account screens may refuse it. Requesting offline_access with the initial scope permits refresh token issuance; refresh tokens rotate within the original eight-hour session. An ID token is never a management API token. For an application-shaped code sample, run the injected protocol tests in examples/node, examples/fastapi, or examples/native. Those examples need a separately approved client before a real provider sign-in.

Next step

Read client registration for the remaining multi-client gate, then web sign-in or native sign-in. Do not route a product’s workforce traffic to the disposable portal client.

Popular

Browse by section