Skip to Content

M2M Client Credentials

Machine-to-Machine (M2M)-Authentifizierung wird verwendet, wenn ein Backend-Dienst oder automatisierter Prozess eine API aufrufen muss, ohne dass ein Mensch anwesend ist. Auris implementiert den OAuth2 client_credentials Grant (RFC 6749 Abschnitt 4.4) und stellt Access Tokens direkt an vertrauliche Clients aus.

Häufige Anwendungsfälle:

  • Ein Hintergrund-Job, der Benutzerdaten aus der Auris Management API lesen muss
  • Ein Microservice, der Berechtigungen für API-Anfragen validiert
  • Eine CI/CD-Pipeline, die Rollen und Anwendungskonfiguration verwaltet
  • Ein Backend-Dienst, der einen anderen Dienst aufruft, der Auris-Tokens validiert

Funktionsweise

Der client_credentials Flow umfasst keinen Benutzer, keine Login-Seite und keine Weiterleitung. Der Client sendet seine Anmeldeinformationen direkt an den Token-Endpunkt und erhält ein Access Token:

  1. Client sendet client_id, client_secret, grant_type=client_credentials und optionale scope an den Token-Endpunkt
  2. Auris validiert die Anmeldeinformationen und prüft, ob die angeforderten Scopes für die Anwendung erlaubt sind
  3. Auris stellt ein JWT-Access-Token mit type: 'm2m' und den gewährten Scopes im scope-Claim aus
  4. Der Client präsentiert das Access Token als Bearer-Token bei nachgelagerten API-Aufrufen

Tokens sind kurzlebig (Standard: 60 Minuten) und sollten bis zum Ablauf gecacht und wiederverwendet werden.


Console-Einrichtung

M2M-Anwendung erstellen

Gehe in der Auris Console zu Applications → Create Application und wähle M2M als Anwendungstyp.

M2M-Anwendungen haben keine Redirect-URIs oder Login-Seiten — nur Anmeldeinformationen und Scopes.

Erlaubte Scopes konfigurieren

Wähle unter dem Tab M2M Scopes auf der Anwendungsdetailseite, welche Scopes die Anwendung anfordern darf. Verfügbare Scopes sind nach Ressource organisiert (z. B. read:users, manage:roles, view:organizations).

Anmeldeinformationen kopieren

Kopiere vom Tab Credentials die Client ID und das Client Secret.

Client Secrets werden nur einmal bei der Erstellung angezeigt. Speichere das Secret sicher (z. B. in einem Secrets Manager oder als Umgebungsvariable). Bei Verlust des Secrets verwende die Schaltfläche Rotate Secret, um ein neues zu generieren.

Anmeldeinformationen sicher speichern

Setze die Anmeldeinformationen als Umgebungsvariablen in deiner Deployment-Umgebung. Kodiere sie nie im Quellcode oder committe sie in die Versionskontrolle.

AURIS_CLIENT_ID=your-m2m-client-id AURIS_CLIENT_SECRET=your-m2m-client-secret AURIS_DOMAIN=auth.yourdomain.com

Implementierung

import { AurisClient } from '@auris/js' const auris = new AurisClient({ domain: process.env.AURIS_DOMAIN, clientId: process.env.AURIS_CLIENT_ID, }) // M2M-Access-Token mit bestimmten Scopes anfordern const token = await auris.getM2MToken( process.env.AURIS_CLIENT_SECRET, ['read:users', 'manage:roles'], ) console.log('Access Token:', token.accessToken) console.log('Läuft ab in:', token.expiresIn, 'Sekunden') // Token verwenden, um die Auris Management API aufzurufen const usersResponse = await fetch('https://auth.yourdomain.com/api/users', { headers: { Authorization: `Bearer ${token.accessToken}` }, }) const users = await usersResponse.json()

Token-Format

M2M-Access-Tokens sind JWTs mit folgenden Claims:

{ "iss": "https://auth.yourdomain.com", "sub": "your-client-id", "aud": "https://auth.yourdomain.com", "exp": 1735000000, "iat": 1734996400, "type": "m2m", "scope": "read:users manage:roles", "clientId": "your-client-id" }

Der type: 'm2m'-Claim unterscheidet diese Tokens von Benutzer-Tokens (type: 'user'). Deine APIs können diesen Claim verwenden, um zwischen Benutzer- und Service-Anfragen zu unterscheiden.


Token-Caching

M2M-Tokens sollten für ihre gesamte Gültigkeitsdauer gecacht werden, um unnötige Netzwerkaufrufe an den Token-Endpunkt zu vermeiden:

class TokenCache { #token = null #expiresAt = 0 async getToken(auris, clientSecret, scopes) { // Gecachten Token zurückgeben, wenn noch gültig (mit 60s Puffer) if (this.#token && Date.now() < this.#expiresAt - 60_000) { return this.#token } const result = await auris.getM2MToken(clientSecret, scopes) this.#token = result.accessToken this.#expiresAt = Date.now() + result.expiresIn * 1000 return this.#token } } const cache = new TokenCache() // In deinen API-Aufrufen: const token = await cache.getToken(auris, clientSecret, ['read:users'])

DPoP-Token-Bindung

Für Umgebungen, die senderkonstante Tokens erfordern, unterstützt Auris DPoP (Demonstrating Proof of Possession, RFC 9449). DPoP bindet das Access Token an den öffentlichen Schlüssel eines bestimmten Clients — ein gestohlenes Token kann ohne den entsprechenden privaten Schlüssel nicht von einem anderen Client verwendet werden.

DPoP für M2M-Anwendungen aktivieren:

  1. DPoP auf der M2M-Anwendung in Console → Applications → [App] → Settings → Require DPoP aktivieren
  2. Ein Schlüsselpaar in deinem Dienst generieren und bei jeder Token-Anfrage und jedem API-Aufruf einen DPoP-Proof-Header einschließen
import { createDpopProof } from '@auris/js' // DPoP-Schlüsselpaar generieren (einmalig beim Dienst-Start) const dpopKeyPair = await crypto.subtle.generateKey( { name: 'ECDSA', namedCurve: 'P-256' }, false, // nicht extrahierbar ['sign', 'verify'], ) // Token mit DPoP anfordern const dpopProof = await createDpopProof(dpopKeyPair, 'POST', tokenEndpointUrl) const tokenResponse = await fetch(tokenEndpointUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'DPoP': dpopProof, }, body: new URLSearchParams({ grant_type: 'client_credentials', client_id: clientId, client_secret: clientSecret, }), })

Eigene APIs mit M2M-Tokens schützen

Wenn deine Backend-APIs Auris-M2M-Tokens von anderen Diensten akzeptieren, validiere die Token-Signatur mit dem Auris-JWKS-Endpunkt:

import { verifyToken } from '@auris/js/jwt-verify' export async function authMiddleware(req, res, next) { const authHeader = req.headers.authorization if (!authHeader?.startsWith('Bearer ')) { return res.status(401).json({ error: 'Fehlender Authorization-Header' }) } const token = authHeader.slice(7) try { const payload = await verifyToken(token, { jwksUrl: 'https://auth.yourdomain.com/.well-known/jwks.json', issuer: 'https://auth.yourdomain.com', }) // Prüfen, ob es ein M2M-Token ist (kein Benutzer-Token) if (payload.type !== 'm2m') { return res.status(403).json({ error: 'Benutzer-Tokens nicht auf diesem Endpunkt erlaubt' }) } // Erforderliche Scopes prüfen const scopes = payload.scope?.split(' ') ?? [] if (!scopes.includes('call:your-service')) { return res.status(403).json({ error: 'Unzureichende Scopes' }) } req.clientId = payload.sub next() } catch (err) { return res.status(401).json({ error: 'Ungültiges Token' }) } }

API-Endpunkte

POST/api/auth/token

Token-Endpunkt. grant_type=client_credentials, client_id, client_secret und optionale scope setzen. Gibt ein Access Token und Ablaufzeit zurück.

GET/api/applications/:id/m2m-scopesRequires: manage:applications

Listet die erlaubten Scopes für eine M2M-Anwendung auf.

POST/api/applications/:id/m2m-scopesRequires: manage:applications

Aktualisiert die erlaubten Scopes für eine M2M-Anwendung.


Verwandte Anleitungen