Skip to content

SAML with authentik

Tested against authentik 2026.5. Goal: login through authentik works and your admin user gets org_admin instead of "forbidden".

All steps happen in the Admin Interface (https://<authentik-host>/if/admin/). Menu map for the settings people struggle to find:

WhatWhere
Create a groupDirectory → Groups
Property mappings (groups/email)Customization → Property Mappings
Edit provider (ACS, certs, mappings)Applications → Providers
Create/upload certificatesSystem → Certificates

The two "missing" fields

The property-mapping selector and the Verification Certificate field live on the provider under the collapsed "Advanced protocol settings" section — expand it first.

1. Create the admin group

Directory → Groups → Create

  • Name: orbital-admins (any name — but exactly this string goes into the OrbitalReg values later).
  • Open the group → Users tab → Add existing user → add your login user.

2. Property mappings

With saml.idpPreset: "authentik" (recommended), OrbitalReg reads authentik's default SAML property mappings — including the stock groups mapping (http://schemas.xmlsoap.org/claims/Group). No custom mapping is needed; skip to step 3.

Running without the preset (entra default)?

Without the preset, OrbitalReg only reads Microsoft's groups URI, so you must create a custom mapping. Customization → Property Mappings → Create → "SAML Provider Property Mapping":

  • Name: OrbitalReg Groups

  • SAML Attribute Name:http://schemas.microsoft.com/ws/2008/06/identity/claims/groups

  • Expression:

    python
    return [group.name for group in request.user.ak_groups.all()]

Then select it on the provider (step 3). The preset exists precisely to make this step unnecessary.

3. Configure the provider

Applications → Providers → <your OrbitalReg provider> → Edit

Protocol settings:

  • ACS URL: https://<domain>/saml/acs — https, no trailing slash (the SP compares exactly).
  • Issuer / Audience: https://<domain>/saml/metadata — must match saml.entityID in the values exactly.
  • Service Provider Binding: Post. The default Redirect delivers the SAML response as GET, and OrbitalReg's ACS accepts only POST → HTTP 405 after login.
  • Signing Certificate: pick a keypair (e.g. "authentik Self-signed Certificate"). It signs the assertion and lands in the metadata that OrbitalReg fetches.

Property mappings ("Available / Selected" two-column selector) — select:

  • authentik default SAML Mapping: Email
  • authentik default SAML Mapping: Name
  • the default Groups mapping (or OrbitalReg Groups if you created the custom one)

NameID Property Mapping: authentik default SAML Mapping: Email (OrbitalReg identifies users by email).

Advanced protocol settings (expand it):

  • Verification Certificate: the OrbitalReg SP certificate (step 4). Required because OrbitalReg signs its login requests; without it authentik may reject or ignore the request.

4. Register the SP certificate ("the raw cert")

authentik must know the public half of the SP keypair OrbitalReg signs with. If you don't have one yet:

bash
openssl req -x509 -newkey rsa:2048 -nodes \
  -keyout sp.key -out sp.crt -days 3650 -subj "/CN=orbitalreg-sp"

System → Certificates → Create

  • Name: orbitalreg-sp
  • Certificate: paste the contents of sp.crt
  • Private Key: leave empty (authentik only verifies)

Back in step 3, select it as the Verification Certificate. On the OrbitalReg side, sp.crt + sp.key go into the Helm secret (saml.existingSecret or saml.certPEM/keyPEM).

5. Copy the metadata URL

Applications → Providers → <provider> → "Metadata download" URL:

https://<authentik-host>/application/saml/<application-slug>/metadata/

Use the public authentik host — authentik builds the endpoint URLs in the metadata from the host the metadata was fetched on. This URL becomes saml.idpMetadataURL.

6. Values + deploy

A complete example ships as charts/orbitalreg/values-authentik.yaml.example. The essentials:

yaml
saml:
  enabled: true
  idpPreset: "authentik"
  rootURL: "https://registry.example.com"
  entityID: "https://registry.example.com/saml/metadata"
  idpMetadataURL: "https://<authentik-host>/application/saml/<app-slug>/metadata/"
  existingSecret: "orbitalreg-saml-sp"   # TLS secret with sp.crt / sp.key

auth:
  adminGroups:
    - "orbital-admins"                   # exact group name from step 1
bash
helm upgrade orbitalreg charts/orbitalreg -n <ns> -f values-authentik.yaml

7. Verify

  1. Log out completely (including the authentik session), log back in.
  2. Open https://<domain>/auth/whoami: groups must contain orbital-admins, roles must contain org_admin.

If groups stays empty, add your login email to auth.adminGroups as an immediate fallback (it always matches, because the email is always in the assertion), redeploy, re-login — then debug the group mapping calmly.

8. Optional: IdP-initiated login

By default OrbitalReg only accepts a SAML response that answers an AuthnRequest it issued (SP-initiated: user clicks "Log in" on OrbitalReg first). Clicking the authentik application tile directly skips that step — authentik posts an unsolicited assertion — which OrbitalReg rejects unless you opt in.

yaml
saml:
  allowIdpInitiated: true
  idpInitiatedRelayStates: ["/"]   # optional; "/" is the default anyway

CSRF / login-forgery trade-off

Accepting an unsolicited assertion is the well-known SAML IdP-initiated weakness: there is no SP-issued request ID to match the response against, so anyone who can get a captured assertion POSTed to /saml/acs (e.g. a malicious page that replays one) can log a victim into an attacker-chosen session. Only turn this on if you trust authentik to gate the application tile behind its own auth, and keep idpInitiatedRelayStates limited to the paths you actually want IdP-initiated logins to land on — anything outside that whitelist is rewritten to / rather than followed, which closes the matching open-redirect angle (an IdP-supplied RelayState would otherwise become the raw post-login redirect target).

After the flag is set, clicking the authentik app tile should land you logged in on the OrbitalReg dashboard.

Troubleshooting

Real cases from the first rollout:

SymptomCauseFix
Pod crashes, saml init failed in logSP can't load idpMetadataURL (TLS, DNS, wrong slug)curl the URL from the pod network; use authentik's "Copy download URL"
"response code null" on login clickMetadata contains internal SSO URLs (fetched via internal address)Set idpMetadataURL to the public authentik URL
Login works, but roles: reader despite correct group in whoamiGroup list joined with commas; env slices split only on whitespace → one giant non-matching stringFixed in current charts (space-joined). Check kubectl exec … env | grep ADMIN_GROUPS
405 after the authentik loginProvider field "Service Provider Binding" is Redirect (default) — response arrives as GET, ACS is POST-onlySet Service Provider Binding = Post
404 on /saml/acsACS URL with trailing slash or different path — exact comparisonACS URL exactly https://<domain>/saml/acs
405 when opening /saml/acs directly in the browserNormal — GET on a POST-only endpointNot an error
groups empty in whoamiMapping not "Selected" on the provider, wrong attribute URI / missing preset, or no fresh login after a mapping changeCheck preset + Selected mappings; log out completely and back in (groups are baked into the session at login)

Reference: what OrbitalReg reads (preset authentik)

OrbitalReg expectsSAML attribute name
Email (identity)http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
Groups (→ role)http://schemas.xmlsoap.org/claims/Group
Display namehttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/name

See the SSO overview for how these map to roles and how to override individual claim names.

Released under the Apache-2.0 License.