Auth
This example runs the PostgreSQL-backed auth middleware as the identity service of a platform, with session and login in front for browser authentication. Other applications share the login through the same session cookie and ask this service for permissions, see Single Page App.
Requirements: a reachable PostgreSQL database (migrations run automatically), a Redis compatible store shared by every Turna that reads the session, and an encryption key.
Identity service
The configuration below runs in its own container, reachable as auth:8080 inside the platform network and published as https://apps.example.com/auth/.
server:
entrypoints:
web:
address: ":8080"
http:
middlewares:
auth:
auth:
prefix_path: /auth
database:
dsn: postgres://auth_app:change-me@postgres:5432/platform?search_path=auth&application_name=auth
encryption:
key: change-me-encryption-key
session:
session:
cookie_name: platform_session
session_key: change-me-32-byte-random-value
store:
active: redis
redis:
address: redis:6379
key_prefix: platform_session_
options:
http_only: true
secure: true
same_site: 2 # lax
auth_skip_paths:
- auth # keeps /auth/oauth2/** and /.well-known/** public
provider:
company:
auth_middleware: auth # in-process token validation and refresh
password_flow: true
passkey: true
oauth2:
client_id: platform-ui # OAuth client registered in auth
scopes: [openid]
set_provider: company
action:
active: token
token:
login_path: /auth/login/
login:
login:
session_middleware: session
path:
base: /auth/login/
info:
title: Example Platform
store:
active: redis
redis:
address: redis:6379
logout:
set:
values:
- logout
routers:
auth:
path:
- /auth/*
- /.well-known/*
middlewares:
- session # sets X-User for the auth API and UI
- auth
login:
path: /auth/login/*
middlewares:
- login
logout:
path: /auth/logout/*
middlewares:
- logout
- login
check:
host: auth # only reachable inside the platform network
path:
- /auth/check
middlewares:
- authThis document holds the database password and the keys, so keep it in Vault rather than in the image: store it as the secret platform/auth and start the container with VAULT_ADDR, VAULT_SECRET_BASE_PATH, CONFIG_NAME_PREFIX=platform and APP_NAME=auth. See Config from Consul or Vault.
How the pieces fit:
authserves the IAM API, OAuth2/OIDC endpoints and the embedded management UI under/auth. Runtime settings (token lifetimes, clients, providers, LDAP, TOTP, passkeys, ...) live in PostgreSQL and are managed through/auth/ui/.sessionreferences the auth middleware by name (auth_middleware), so JWT validation and token refresh happen in-process without HTTP self-calls.auth_skip_pathskeeps the public OAuth2 plane and the public permissions ofauthreachable without a login.loginrenders the login page at/auth/login/./auth/logout/sets thelogoutflag, which makesloginrevoke the tokens and delete the session.checkis the permission endpoint other Turna instances call withiam_check. Thehost: authrule matches the internal service name, so the endpoint is not published on the public host.cookie_name,session_keyand the Rediskey_prefixare the contract with the other applications: every Turna that should see the same login uses the same three values.
Providers from the auth UI
Instead of the static provider map, the session can read its providers from the auth UI (Federation → Session providers) with provider_source.auth_middleware: auth. Changes then apply on the next request without a restart. See provider_source.
First steps
- Open
https://apps.example.com/auth/ui/. With noadmin.permissionset, access is bootstrap-open. - Create a user, a role, and the OAuth client
platform-uiused by the session provider. - Set the
adminruntime namespace to lock down the management UI:
curl -X PUT https://apps.example.com/auth/v1/settings/admin \
-d '{"value":{"permission":"turna.auth.admin","allow_missing_x_user":false}}'For a single local instance, a file session store and a plain dsn are enough; Redis is needed as soon as more than one Turna reads the session. See the auth reference for runtime settings, LDAP sync, API keys, device flow, and SAML.