Authentication and access
Memory Layer defaults to single_user, preserving existing local installs. Set
auth.mode = "multi_user" to use Authentik for browser identity and scoped
Memory Layer service tokens for CLI, TUI, watchers, relays, and HTTP MCP.
Identity split
| Actor | Authentication | Secret location |
|---|---|---|
| Browser user | Authentik OIDC Authorization Code + PKCE | HttpOnly Memory Layer session cookie |
| CLI, TUI, watcher, agent | Memory Layer mlt_... service token | Process environment or secret manager |
| HTTP MCP | Memory Layer service token; cookies ignored | MCP client secret configuration |
| Relay | Original caller credential forwarded to primary | No privilege substitution |
Authentik authenticates people. OpenBao is recommended for distributing machine secrets, but Memory Layer does not call OpenBao at runtime.
Permission sets and role presets
Authorization in v2 checks explicit permissions. Role names remain convenient
presets, and applicable grants are combined; the service does not authorize by
comparing an ordinal reader < writer < operator < admin ladder.
| Role | Typical capability |
|---|---|
reader | memory_read, bundle_export |
writer | Reader preset plus activity_capture |
operator | Writer preset plus memory_curate, loops_run, bundle_import |
admin | Every permission, including delete, loop configuration, embeddings management, access management, and system administration |
A global preset applies to every project. Explicit memberships and Authentik
group mappings apply to named projects. /v1/auth/me exposes the expanded
permission names so clients do not need to infer capabilities from the role
label.
Authentik setup
- In Authentik, create an application with an OAuth2/OIDC provider.
- Use a confidential client and select a signing key.
- Add the strict redirect URI
https://memory.example.com/v1/auth/callback. - Include the
openid,profile, andemailscope mappings. Authentik's default profile scope includes group membership. - Record the application slug, issuer URL, client ID, and client secret.
Authentik documents the current provider workflow in Create an OAuth2 provider and the issuer/scope behavior in OAuth 2.0 provider.
Service configuration
[auth]
mode = "multi_user"
public_base_url = "https://memory.example.com"
session_ttl = "12h"
multi_user_legacy_token_enabled = false
[auth.oidc]
issuer_url = "https://auth.example.com/application/o/memory/"
client_id = "memory-layer"
client_secret_env = "MEMORY_LAYER_OIDC_CLIENT_SECRET"
scopes = ["openid", "profile", "email"]
groups_claim = "groups"
[[auth.group_mappings.rules]]
group = "memory-admins"
role = "admin"
global = true
[[auth.group_mappings.rules]]
group = "memory-writers"
role = "writer"
project = "memory"Put the client secret in the adjacent environment file:
MEMORY_LAYER_OIDC_CLIENT_SECRET=replace-with-authentik-client-secretpublic_base_url must be the browser-visible URL, including the HTTPS scheme.
Memory Layer uses it for the callback URI and exact Origin checks.
Service principals
memory auth whoami
memory auth token create \
--name hermes \
--project memory \
--role writer \
--ttl 30d
export MEMORY_LAYER_CLIENT_TOKEN='mlt_...'
memory auth whoami --jsonThe raw token is displayed once. Memory Layer stores only its SHA-256 hash. Store it in OpenBao or another secret manager before closing the output.
Grant the same principal another project:
memory auth membership grant \
--principal <principal-uuid> \
--project another-project \
--role readerGlobal admins can perform the same work from the web UI's Access tab.
Migration
- Configure Authentik and at least one global-admin group while still in
single_usermode. - Set the OIDC secret environment variable and restart the service.
- Switch to
multi_userand verify a browser admin can sign in. - Issue project-scoped service tokens for every non-browser workload.
- Disable
multi_user_legacy_token_enabledafter migration.
Returning to single_user is a config rollback. Do not reverse the auth
migration; retaining the rows preserves the audit trail.
Troubleshooting
| Symptom | Meaning | Action |
|---|---|---|
401 | Credential missing, invalid, expired, or revoked | Set MEMORY_LAYER_CLIENT_TOKEN, sign in again, or rotate the token. |
403 | Identity is valid but role/project access is insufficient | Check group mapping or explicit membership. |
Login returns 503 | Authentik discovery or client secret unavailable | Check issuer URL, provider health, and client_secret_env. |
Browser write returns 403 | Origin or CSRF check failed | Verify public_base_url, HTTPS proxy headers, and cookies. |
| MCP rejects browser session | Expected: HTTP MCP is cookie-blind | Configure a scoped service token in the MCP client. |
Existing browser sessions and service tokens keep working during an Authentik outage; only new browser logins depend on provider discovery.