Aurora Nexus
Aurora NexusSécurité

Contrat auth OIDC Nexus

contrat technique claims, sessions, JWKS, RBAC, step-up et tests d'acceptation

Objectif

Ce document fixe le contrat technique entre authentik et Nexus pour les lots NX-AUTH-002 a NX-AUTH-008.

Il complete l'ADR 04_Securite/23-ADR-Authentik-OIDC-MFA.md.

Variables cible

Ces variables sont le contrat cible. Elles seront ajoutees ou alignees dans .env.example par le lot qui implemente le comportement correspondant.

# OIDC / authentik
OIDC_ENABLED=false
OIDC_ISSUER_URL=https://auth.example.com/application/o/nexus/
OIDC_CLIENT_ID=nexus-ui
OIDC_CLIENT_SECRET=
OIDC_REDIRECT_URI=https://nexus.example.com/auth/callback
OIDC_POST_LOGOUT_REDIRECT_URI=https://nexus.example.com/
OIDC_SCOPES=openid email profile groups nexus.roles
OIDC_AUDIENCE=nexus-api
OIDC_ALLOWED_ALGORITHMS=RS256
OIDC_JWKS_CACHE_TTL_SECONDS=3600

# Sessions Nexus
SESSION_COOKIE_NAME=nexus_session
SESSION_COOKIE_SECURE=true
SESSION_COOKIE_SAMESITE=lax
SESSION_TTL_SECONDS=28800
STEP_UP_MAX_AGE_SECONDS=900

# Migration auth locale
LOCAL_PASSWORD_LOGIN_ENABLED=false
BREAK_GLASS_LOGIN_ENABLED=false
BREAK_GLASS_EMAILS=srey@auroramind.fr
LOCAL_USER_PASSWORD_CREATE_ENABLED=false
LOCAL_PASSWORD_ADMIN_RESET_ENABLED=false
NEXT_PUBLIC_BREAK_GLASS_EMAILS=srey@auroramind.fr

# Machine-to-machine
M2M_REQUIRED_AUDIENCE=nexus-api
M2M_DEFAULT_TOKEN_TTL_SECONDS=3600

# Webhooks
WEBHOOK_SIGNATURE_TOLERANCE_SECONDS=300
WEBHOOK_HMAC_ALGORITHM=sha256

Flux humain

Login

  1. L'utilisateur ouvre Nexus sans session valide.
  2. Nexus genere state, nonce, code_verifier et code_challenge.
  3. Nexus redirige vers l'authorization endpoint authentik.
  4. authentik authentifie l'utilisateur et applique les politiques MFA.
  5. authentik redirige vers /auth/callback.
  6. Nexus echange le code cote serveur, valide state, nonce, token response et ID/access token.
  7. Nexus cree une session locale httpOnly.

Stockage tokens

Les tokens OIDC ne doivent pas etre stockes durablement dans le navigateur.

V1 recommandee :

  • pas de refresh token cote navigateur;
  • session Nexus bornee par SESSION_TTL_SECONDS;
  • renouvellement via nouveau login authentik quand necessaire;
  • si offline_access devient necessaire, le refresh token doit rester cote serveur et etre chiffre ou reference par session.

Logout

Le logout doit :

  • revoquer la session Nexus locale;
  • supprimer le cookie;
  • rediriger vers l'end session endpoint authentik si configure;
  • rester robuste si authentik est temporairement indisponible.

Discovery et JWKS

Nexus charge la configuration depuis :

{OIDC_ISSUER_URL}/.well-known/openid-configuration

En mode issuer authentik par provider, l'issuer inclut le chemin /application/o/<slug>/.

Le discovery document doit fournir :

  • issuer;
  • authorization_endpoint;
  • token_endpoint;
  • userinfo_endpoint si utilise;
  • jwks_uri;
  • end_session_endpoint si disponible;
  • grant_types_supported;
  • code_challenge_methods_supported.

Nexus doit refuser la configuration si issuer ne correspond pas exactement a OIDC_ISSUER_URL normalise.

Validation JWT

Nexus valide au minimum :

ElementRegle
Signatureverification via JWKS
Algorithmepresent dans OIDC_ALLOWED_ALGORITHMS; HS256 interdit pour OIDC
Issueregal a OIDC_ISSUER_URL
Audiencecontient OIDC_AUDIENCE ou l'OIDC_CLIENT_ID Authentik
Expirationexp futur
Not beforenbf respecte si present
Issued atiat raisonnable
Subjectsub non vide
Scopescope ou scp parse
Tenanttenant_id ou mapping Nexus valide

Claims requis

Humain

{
  "iss": "https://auth.example.com/application/o/nexus/",
  "aud": ["nexus-api"],
  "sub": "authentik-user-id",
  "email": "user@example.com",
  "name": "User Name",
  "groups": ["tenant-a-nexus-admin"],
  "scope": "openid email profile nexus.query nexus.search",
  "tenant_id": "tenant-a",
  "auth_time": 1781540000,
  "amr": ["pwd", "mfa", "webauthn"]
}

Machine

{
  "iss": "https://auth.example.com/application/o/nexus-m2m/",
  "aud": ["nexus-api"],
  "sub": "service-account-or-client-subject",
  "client_id": "nexus-n8n-worker",
  "scope": "nexus.ingest",
  "tenant_id": "tenant-a"
}

Machine-to-machine Authentik

Le mode M2M retenu pour Nexus est le flux OAuth2 client_credentials fourni par Authentik.

Contrat Nexus :

  • le token est valide par discovery/JWKS comme les autres tokens OIDC;
  • aud doit contenir OIDC_AUDIENCE ou l'OIDC_CLIENT_ID du provider Authentik;
  • tenant_id est obligatoire;
  • scope ou scp porte les droits Nexus minimaux;
  • client_id ou azp identifie le client machine;
  • grant_type=client_credentials, gty=client_credentials ou l'absence de claims humains avec client_id classe le principal comme machine.

Les flux machine ne passent jamais par une MFA interactive. La securite repose sur :

  • client/service account dedie par integration;
  • TTL court des access tokens;
  • scopes minimaux (nexus.ingest sans nexus.export si l'integration n'exporte pas);
  • rotation du secret/app password token dans Authentik;
  • absence de secret brut dans le depot Nexus.

Note Authentik : la documentation officielle M2M indique que les clients machine utilisent le grant client_credentials; l'identification se fait cote Authentik par client/service account et l'authentification par token/app password selon la configuration du provider. La configuration exacte reste a valider dans l'interface admin Authentik du tenant cible.

Note audience Authentik : les JWT emis par le provider OAuth2/OIDC Authentik portent l'audience du client_id du provider. Nexus accepte donc OIDC_CLIENT_ID en plus de OIDC_AUDIENCE pour les bearers API.

Exemples de profils :

ClientScopes NexusUsage
nexus-n8n-workernexus.ingestDeposer des documents et lancer l'ingestion.
nexus-intelligence-readernexus.queryLire des context packs / requetes RAG.
nexus-exporternexus.query nexus.exportExport controle, a eviter par defaut.

Rotation recommandee :

  1. Creer un nouveau token/app password cote Authentik.
  2. Mettre a jour le secret dans le coffre runtime de l'integration cliente.
  3. Verifier l'obtention d'un nouveau token client_credentials.
  4. Revoquer l'ancien token/app password.
  5. Verifier qu'aucune valeur brute n'a ete journalisee ni commitee.

Principal Nexus

Le backend normalise les claims vers ce modele logique :

class AuthPrincipal:
    subject: str
    email: str | None
    name: str | None
    tenant_id: str
    groups: list[str]
    scopes: set[str]
    roles: set[str]
    auth_time: int | None
    amr: list[str]
    is_machine: bool
    client_id: str | None

is_machine vaut true si le token vient d'un flux M2M valide ou si client_id/grant type et policy Nexus le classent explicitement comme machine.

Scopes API Nexus

Scopes cibles :

nexus.query
nexus.search
nexus.ingest
nexus.export
nexus.delete
nexus.admin
nexus.users.manage
nexus.api_keys.manage
nexus.connectors.manage
nexus.audit.read

Regle : l'absence de scope requis refuse l'appel avant toute logique metier.

Roles Nexus

Roles cibles :

tenant_owner
tenant_admin
corpus_manager
analyst
reader
external_app
ingestion_worker

Mapping groupe recommande pour POC :

<tenant>-nexus-owner            -> tenant_owner
<tenant>-nexus-admin            -> tenant_admin
<tenant>-nexus-corpus-manager   -> corpus_manager
<tenant>-nexus-analyst          -> analyst
<tenant>-nexus-reader           -> reader
<tenant>-nexus-n8n-worker       -> ingestion_worker
<tenant>-nexus-external-app     -> external_app

Pour production, Nexus doit verifier le mapping via une regle ou une table interne. Le prefixe de groupe seul ne suffit pas comme preuve tenant.

Endpoints attendus

EndpointLotRegle
GET /auth/loginNX-AUTH-002redirection authentik
GET /auth/callbackNX-AUTH-002echange code server-side
POST /auth/logout ou GET /auth/logoutNX-AUTH-002logout local + IdP
GET /auth/meNX-AUTH-002/003principal Nexus courant
dependencies FastAPINX-AUTH-003/004get_current_principal, require_scope, require_role
step-up dependencyNX-AUTH-008require_recent_mfa

Migration depuis l'auth locale

Les lots doivent conserver un chemin de rollback tant que l'OIDC n'est pas valide en staging.

Plan cible :

  1. NX-AUTH-002 ajoute OIDC sans supprimer brutalement l'ancien code.
  2. NX-AUTH-005 masque et borne le login password local.
  3. NX-AUTH-005 desactive reset password en flux normal.
  4. Les champs DB existants restent tant qu'une migration destructive n'est pas explicitement validee.

Etat NX-AUTH-005:

  • le login local password est refuse si LOCAL_PASSWORD_LOGIN_ENABLED=false, sauf si BREAK_GLASS_LOGIN_ENABLED=true et que l'e-mail appartient a BREAK_GLASS_EMAILS;
  • les evenements d'authentification distinguent oidc, password_legacy et break_glass;
  • la creation admin d'un utilisateur Nexus en mode OIDC peut generer un hash aleatoire non connu plutot que demander un mot de passe utilisateur;
  • le reset password admin est bloque hors break-glass si LOCAL_PASSWORD_ADMIN_RESET_ENABLED=false;
  • l'UI login affiche Auroramind Secure Login comme action principale quand NEXT_PUBLIC_OIDC_ENABLED=true, avec le formulaire local comme secours visible.

Tests d'acceptation

OIDC/JWT

  • token valide accepte;
  • token expire refuse;
  • issuer incorrect refuse;
  • audience incorrecte refusee;
  • algorithme non autorise refuse;
  • JWKS cache utilise puis rafraichi;
  • scope manquant refuse.

RBAC tenant

  • utilisateur sans nexus.query refuse sur query;
  • tenant A ne lit pas tenant B;
  • role admin tenant ne devient pas admin global sans mapping Nexus;
  • refus audite.

M2M

  • client avec nexus.ingest autorise sur ingestion;
  • client sans scope requis refuse;
  • logs affichent machine/client distinctement d'un utilisateur humain;
  • aucune MFA interactive.

Step-up

  • action sensible refusee si auth_time trop ancien;
  • admin avec e-mail OTP seul refuse si amr/acr permet la distinction;
  • action sensible auditee.

Webhooks

  • signature valide acceptee;
  • signature invalide refusee;
  • timestamp trop ancien refuse;
  • key_id inconnu refuse;
  • secret jamais logue.

Stop conditions pour implementation

  • authentik ne fournit pas une cle de signature asymetrique/JWKS;
  • issuer ou audience non stabilises;
  • claims tenant_id, groups, scope/scp impossibles a obtenir ou mapper;
  • besoin d'exposer un secret client au navigateur;
  • absence de strategie break-glass;
  • impossibilite de tester avec JWKS fake local.

On this page