JavaScript SDK (@auris/js)
@auris/js v0.1.0@auris/js ist das Basis-SDK für Auris. Es ist eine abhängigkeitsfreie Bibliothek, die in Browsern, Node.js 18+ und Edge Runtimes (Cloudflare Workers, Vercel Edge, Deno) funktioniert. Sowohl ESM- (import) als auch CJS- (require) Builds sind enthalten, zusammen mit vollständigen TypeScript-Deklarationen.
Die React- und Next.js-SDKs sind dünne Wrapper um @auris/js. Wenn du eine framework-unabhängige Anwendung entwickelst oder die Low-Level-API benötigst, verwende dieses Paket direkt.
Installation
npm install @auris/jspnpm add @auris/jsyarn add @auris/jsAurisClient
AurisClient ist der Haupt-Einstiegspunkt. Pro Anwendung eine Instanz erstellen.
Konstruktor
import { AurisClient } from '@auris/js'
const auris = new AurisClient({
domain: 'auth.yourdomain.com', // Dein Auris-Tenant-Domain (erforderlich)
clientId: 'app_xxxxx', // Anwendungs-Client-ID aus der Console (erforderlich)
redirectUri: 'http://localhost:3000/callback', // Muss einer registrierten Callback-URL entsprechen (für PKCE erforderlich)
tenant: 'my-tenant', // Tenant-Bezeichner als x-tenant-Header (optional, Standard: 'default')
storage: 'localStorage', // Token-Speicher: 'localStorage' | 'sessionStorage' | 'memory' | TokenStore-Instanz
autoRefresh: true, // Access-Tokens vor Ablauf automatisch erneuern (Standard: true)
scope: 'openid profile email', // Anzufordernde OAuth2-Scopes (Standard: 'openid profile email')
})Konfigurationsoptionen:
| Option | Typ | Erforderlich | Standard | Beschreibung |
|---|---|---|---|---|
domain | string | Ja | — | Dein Auris-Tenant-Domain, ohne https:// |
clientId | string | Ja | — | Anwendungs-Client-ID aus der Console |
redirectUri | string | Bedingt | — | Callback-URL für PKCE-Flows. Muss in der Console registriert sein. |
tenant | string | Nein | 'default' | Tenant-Bezeichner als x-tenant-HTTP-Header |
storage | string | TokenStore | Nein | 'localStorage' | Wo Tokens gespeichert werden |
autoRefresh | boolean | Nein | true | Access-Tokens automatisch erneuern, bevor sie ablaufen |
scope | string | Nein | 'openid profile email' | Leerzeichen-getrennte OAuth2-Scopes |
In Edge Runtimes und Node.js-Umgebungen ohne localStorage fällt das SDK automatisch auf In-Memory-Speicher zurück. storage: 'memory' explizit übergeben, um dieses Verhalten in Browser-Umgebungen zu erzwingen.
Authentifizierungs-Methoden
loginWithRedirect(options?)
Initiiert den OAuth2 Authorization Code Flow mit PKCE. Generiert einen Code Verifier und Challenge, speichert den Verifier und leitet den Browser zur Auris-gehosteten Login-Seite weiter.
Signatur:
loginWithRedirect(options?: LoginWithRedirectOptions): Promise<void>Parameter:
| Option | Typ | Beschreibung |
|---|---|---|
login_hint | string | E-Mail-Feld vorausfüllen |
prompt | 'login' | 'none' | login erzwingt Re-Auth. none gibt einen Fehler zurück, wenn keine aktive Sitzung vorhanden ist. |
screen_hint | 'signup' | Öffnet den Registrierungsbildschirm statt des Login-Bildschirms |
connection | string | Erzwingt eine bestimmte SSO-Verbindung |
locale | string | Überschreibt die Sprache der gehosteten Seite (en, it, de, fr, es) |
state | string | Benutzerdefinierter State-Wert. Das SDK generiert einen sicheren Zufallswert, wenn dieser fehlt. |
// Einfache Login-Weiterleitung
await auris.loginWithRedirect()
// Registrierungsbildschirm öffnen
await auris.loginWithRedirect({ screen_hint: 'signup' })
// E-Mail vorausfüllen und Re-Authentifizierung erzwingen
await auris.loginWithRedirect({ login_hint: '[email protected]', prompt: 'login' })handleRedirectCallback()
Schließt den OAuth2-PKCE-Flow ab, nachdem der Benutzer zur Anwendung zurückgekehrt ist. Liest code und state aus der aktuellen URL, validiert den State, tauscht den Code gegen Tokens und speichert das Ergebnis.
Diese Methode genau einmal auf der Callback-Seite aufrufen, wenn diese zum ersten Mal lädt.
Signatur:
handleRedirectCallback(): Promise<AuthResult>const result = await auris.handleRedirectCallback()
if (result.user) {
console.log('Angemeldet als', result.user.email)
window.location.href = '/dashboard'
}login(email, password)
Direkte E-Mail/Passwort-Authentifizierung ohne Weiterleitung. Gibt Tokens sofort zurück.
Signatur:
login(email: string, password: string): Promise<AuthResult>Bei der direkten Anmeldung werden Zugangsdaten an deinen Anwendungsserver gesendet. Es wird nicht für Browser-Anwendungen empfohlen, da die Sicherheitsvorteile der gehosteten Login-Seite (CAPTCHA, Rate Limiting, Suspicious Login Detection, MFA) umgangen werden. loginWithRedirect() für Endbenutzer-Authentifizierung in Browser-Apps verwenden.
const result = await auris.login('[email protected]', 'hunter2')
console.log(result.user.id)signup(email, password, options?)
Registriert einen neuen Benutzer und gibt sofort Tokens zurück.
Signatur:
signup(email: string, password: string, options?: SignupOptions): Promise<AuthResult>Optionen:
| Option | Typ | Beschreibung |
|---|---|---|
firstName | string | Vorname des Benutzers |
lastName | string | Nachname des Benutzers |
username | string | Benutzername (muss im Tenant eindeutig sein) |
metadata | Record<string, unknown> | Benutzerdefinierte Metadaten, die am Konto gespeichert werden |
const result = await auris.signup('[email protected]', 'securepassword', {
firstName: 'Bob',
lastName: 'Smith',
})logout(options?)
Widerruft das Refresh-Token, löscht gespeicherte Tokens und leitet optional den Browser weiter.
Signatur:
logout(options?: LogoutOptions): Promise<void>Optionen:
| Option | Typ | Beschreibung |
|---|---|---|
returnTo | string | URL, zu der nach dem Abmelden weitergeleitet wird. Muss den gleichen Origin wie deine redirectUri haben. |
// Tokens löschen und zur Startseite weiterleiten
await auris.logout({ returnTo: 'http://localhost:3000' })
// Tokens löschen ohne Weiterleitung (z.B. in einem Node.js-Kontext)
await auris.logout()getUser()
Gibt den aktuell authentifizierten Benutzer aus dem gespeicherten ID-Token zurück. Gibt null zurück, wenn der Benutzer nicht authentifiziert ist.
Signatur:
getUser(): Promise<UserInfo | null>const user = await auris.getUser()
if (user) {
console.log(user.id) // Auris-Benutzer-ID
console.log(user.email)
console.log(user.roles) // string[] — zugewiesene Rollen
console.log(user.metadata) // Record<string, unknown>
}isAuthenticated()
Gibt true zurück, wenn der Benutzer ein gültiges (nicht abgelaufenes) Access-Token hat.
Signatur:
isAuthenticated(): Promise<boolean>if (await auris.isAuthenticated()) {
// Authentifizierte Operationen durchführen
}getAccessToken()
Gibt das aktuelle Access-Token zurück. Wenn autoRefresh aktiviert ist und das Token abgelaufen ist, wird automatisch das Refresh-Token gegen ein neues Access-Token getauscht, bevor es zurückgegeben wird.
Signatur:
getAccessToken(): Promise<string | null>const token = await auris.getAccessToken()
// Token in API-Anfragen verwenden
const response = await fetch('/api/data', {
headers: { Authorization: `Bearer ${token}` },
})refreshToken()
Tauscht das gespeicherte Refresh-Token manuell gegen ein neues Access-Token- und Refresh-Token-Paar.
Signatur:
refreshToken(): Promise<AuthResult>const result = await auris.refreshToken()
console.log(result.accessToken)loginWithMagicLink(email)
Sendet eine Magic-Link-E-Mail an die angegebene Adresse. Der Benutzer klickt auf den Link in der E-Mail, um die Authentifizierung über verifyMagicLink() abzuschließen.
Signatur:
loginWithMagicLink(email: string): Promise<void>await auris.loginWithMagicLink('[email protected]')
// Weiterleiten oder "Überprüfe deine E-Mails"-Nachricht anzeigenverifyMagicLink(token)
Verifiziert ein Magic-Link-Token (aus der URL extrahiert, auf die der Benutzer geklickt hat). Gibt Tokens und Benutzerinformationen bei Erfolg zurück.
Signatur:
verifyMagicLink(token: string): Promise<AuthResult>const urlParams = new URLSearchParams(window.location.search)
const token = urlParams.get('token')
if (token) {
const result = await auris.verifyMagicLink(token)
console.log('Authentifiziert:', result.user)
}forgotPassword(email)
Sendet eine Passwortzurücksetzungs-E-Mail an die angegebene Adresse.
Signatur:
forgotPassword(email: string): Promise<void>await auris.forgotPassword('[email protected]')loginWithSocial(provider)
Leitet den Benutzer zum angegebenen sozialen Identity Provider weiter. Auris verwaltet den Provider-OAuth-Flow und gibt den Benutzer mit einem Authorization Code zu deiner redirectUri zurück.
Signatur:
loginWithSocial(provider: SocialProvider): Promise<void>Unterstützte Provider:
type SocialProvider =
| 'google'
| 'github'
| 'microsoft'
| 'apple'
| 'facebook'
| 'discord'
| 'linkedin'
| 'twitter'
| 'slack'await auris.loginWithSocial('google')
await auris.loginWithSocial('github')getM2MToken(clientSecret, scopes?)
Erhält ein Machine-to-Machine-Access-Token mit dem OAuth2-Grant client_credentials. Für Server-zu-Server-API-Aufrufe ohne Benutzerbeteiligung verwenden.
Signatur:
getM2MToken(clientSecret: string, scopes?: string[]): Promise<M2MTokenResult>const result = await auris.getM2MToken('cs_live_xxxxx', ['read:users', 'manage:roles'])
console.log(result.accessToken)
console.log(result.expiresIn) // Sekunden bis zum AblaufgetM2MToken() niemals in Browser-Code verwenden. Das clientSecret muss ausschließlich serverseitig verbleiben.
onAuthStateChange(callback)
Abonniert Änderungen des Authentifizierungsstatus. Der Callback wird ausgelöst, wenn sich der Benutzer anmeldet, abmeldet oder sein Token erneuert wird.
Signatur:
onAuthStateChange(callback: (user: UserInfo | null) => void): UnsubscribeGibt zurück: Unsubscribe — aufrufen, um den Listener zu entfernen.
const unsubscribe = auris.onAuthStateChange((user) => {
if (user) {
console.log('Angemeldet:', user.email)
} else {
console.log('Abgemeldet')
}
})
// Wenn der Listener nicht mehr benötigt wird:
unsubscribe()Berechtigungs-Modul
Zugriff über auris.permissions. Alle Methoden rufen die Auris-API auf und erfordern eine Benutzerauthentifizierung.
check(permissions)
Überprüft, ob der aktuelle Benutzer eine oder alle angegebenen Berechtigungen hat.
Signatur:
check(permissions: string[]): Promise<PermissionCheckResult>const result = await auris.permissions.check(['manage:users', 'view:reports'])
if (result.has('manage:users')) {
// Admin-UI anzeigen
}
if (result.hasAll) {
// Benutzer hat beide Berechtigungen
}checkOne(permission)
Überprüft eine einzelne Berechtigung. Gibt true zurück, wenn erlaubt, sonst false.
Signatur:
checkOne(permission: string): Promise<boolean>const canDelete = await auris.permissions.checkOne('delete:documents')
if (canDelete) {
showDeleteButton()
}listUserPermissions()
Gibt die vollständige Liste der Berechtigungsstrings zurück, die dem aktuellen Benutzer über alle seine Rollen zugewiesen sind.
Signatur:
listUserPermissions(): Promise<string[]>const permissions = await auris.permissions.listUserPermissions()
console.log(permissions) // ['view:documents', 'create:documents', 'manage:users', ...]FGA-Modul
Zugriff über auris.fga. Implementiert Zanzibar-style Fine-Grained Authorization. Erfordert, dass das FGA-Feature auf deinem Tenant aktiviert ist.
check(input)
Überprüft, ob ein Subjekt eine Beziehung zu einem Objekt hat.
Signatur:
check(input: FgaCheckInput): Promise<FgaCheckResult>const result = await auris.fga.check({
objectType: 'document',
objectId: 'doc_abc123',
relation: 'editor',
subjectType: 'user',
subjectId: user.id,
})
if (result.allowed) {
enableEditMode()
}expand(input)
Erweitert eine Beziehung, um alle Subjekte (Benutzer oder Gruppen) aufzulisten, die sie für ein bestimmtes Objekt haben.
const tree = await auris.fga.expand({
objectType: 'project',
objectId: 'proj_xyz',
relation: 'member',
})listObjects(input)
Listet alle Objekt-IDs eines bestimmten Typs auf, für die das Subjekt die angegebene Beziehung hat.
// Alle Dokumente auflisten, die der aktuelle Benutzer anzeigen kann
const documentIds = await auris.fga.listObjects({
objectType: 'document',
relation: 'viewer',
subjectType: 'user',
subjectId: user.id,
})writeTuples(tuples)
Schreibt ein oder mehrere Beziehungs-Tuples in den FGA-Store.
await auris.fga.writeTuples([
{
objectType: 'document',
objectId: 'doc_abc123',
relation: 'editor',
subjectType: 'user',
subjectId: 'usr_456',
},
])deleteTuples(tuples)
Löscht ein oder mehrere Beziehungs-Tuples aus dem FGA-Store.
await auris.fga.deleteTuples([
{
objectType: 'document',
objectId: 'doc_abc123',
relation: 'editor',
subjectType: 'user',
subjectId: 'usr_456',
},
])Management Client
createManagementClient(config) erstellt einen Management-API-Client, der sich mit M2M-client_credentials authentifiziert. In Backend-Code (Node.js-Skripte, API-Routen, CLI-Tools) verwenden, um den Tenant programmatisch zu verwalten.
Signatur:
import { createManagementClient } from '@auris/js'
const mgmt = await createManagementClient({
domain: 'auth.yourdomain.com',
clientId: 'app_xxxxx',
clientSecret: 'cs_live_xxxxx',
tenant: 'my-tenant',
})Benutzer
// Benutzer mit Paginierung auflisten
const { users, total } = await mgmt.users.list({ page: 1, limit: 50 })
// Einzelnen Benutzer nach ID abrufen
const user = await mgmt.users.get('usr_abc123')
// Benutzer erstellen
const newUser = await mgmt.users.create({
email: '[email protected]',
password: 'temporary-password',
firstName: 'Alice',
roles: ['editor'],
})
// Benutzer aktualisieren
await mgmt.users.update('usr_abc123', { firstName: 'Alicia' })
// Benutzer deaktivieren
await mgmt.users.update('usr_abc123', { enabled: false })
// Benutzer löschen
await mgmt.users.delete('usr_abc123')Organisationen
const orgs = await mgmt.organizations.list()
const org = await mgmt.organizations.get('org_xyz')
const newOrg = await mgmt.organizations.create({ name: 'Acme GmbH', slug: 'acme' })
await mgmt.organizations.update('org_xyz', { name: 'Acme Corporation' })
await mgmt.organizations.delete('org_xyz')Rollen
const roles = await mgmt.roles.list()
const role = await mgmt.roles.get('role_abc')
const newRole = await mgmt.roles.create({ name: 'Editor', description: 'Kann Inhalte bearbeiten' })
await mgmt.roles.update('role_abc', { description: 'Kann Inhalte anzeigen und bearbeiten' })
await mgmt.roles.delete('role_abc')Webhook-Verifizierung
verifyWebhookSignature(options) verifiziert, dass ein eingehender Webhook von Auris gesendet wurde und nicht manipuliert wurde. Verwendet HMAC-SHA256.
import express from 'express'
import { verifyWebhookSignature } from '@auris/js'
const app = express()
app.post('/webhooks/auris', express.raw({ type: 'application/json' }), async (req, res) => {
const isValid = await verifyWebhookSignature({
payload: req.body.toString('utf-8'),
signature: req.headers['x-webhook-signature'],
secret: process.env.AURIS_WEBHOOK_SECRET,
timestamp: req.headers['x-webhook-timestamp'],
})
if (!isValid) {
return res.status(401).json({ error: 'Ungültige Signatur' })
}
const event = JSON.parse(req.body)
console.log('Event empfangen:', event.type)
res.json({ received: true })
})JWT-Verifizierung
verifyJwt(token, jwksUrl) verifiziert ein von Auris ausgestelltes Access-Token anhand der öffentlichen Schlüssel von deinem JWKS-Endpunkt. Abhängigkeitsfrei — verwendet die Web Crypto API in Browsern und Node.js 18+.
import { verifyJwt } from '@auris/js'
try {
const payload = await verifyJwt(
accessToken,
`https://${process.env.AURIS_DOMAIN}/.well-known/jwks.json`
)
console.log('Benutzer-ID:', payload.sub)
console.log('Rollen:', payload.roles)
} catch (err) {
console.error('Token ungültig:', err.message)
}TypeScript-Typen
Wichtige aus @auris/js exportierte Typen:
interface AuthResult {
user: UserInfo
accessToken: string
refreshToken?: string
expiresIn: number
tokenType: 'Bearer'
}
interface UserInfo {
id: string
sub: string
email: string
emailVerified: boolean
name: string
firstName: string
lastName: string
username: string
picture?: string
roles: string[]
metadata: Record<string, unknown>
tenant: string
createdAt: string
}
interface TokenStore {
get(key: string): string | null | Promise<string | null>
set(key: string, value: string): void | Promise<void>
remove(key: string): void | Promise<void>
}
type Unsubscribe = () => voidBenutzerdefinierter Speicher-Adapter
Das TokenStore-Interface implementieren, um Tokens in beliebigen Speicher-Backends zu speichern.
import { AurisClient, TokenStore } from '@auris/js'
class RedisTokenStore implements TokenStore {
constructor(private redis: RedisClient, private prefix = 'auris:') {}
async get(key: string) {
return this.redis.get(this.prefix + key)
}
async set(key: string, value: string) {
await this.redis.set(this.prefix + key, value, { EX: 60 * 60 * 24 })
}
async remove(key: string) {
await this.redis.del(this.prefix + key)
}
}
const auris = new AurisClient({
domain: 'auth.yourdomain.com',
clientId: 'app_xxxxx',
storage: new RedisTokenStore(redisClient),
})Fehlerbehandlung
Alle Async-Methoden werfen bei einem Fehler einen AurisError.
import { AurisClient, AurisError } from '@auris/js'
try {
await auris.login('[email protected]', 'wrongpassword')
} catch (err) {
if (err instanceof AurisError) {
console.error(err.code) // z.B. 'invalid_credentials', 'account_locked', 'mfa_required'
console.error(err.message) // Lesbare Fehlermeldung
console.error(err.status) // HTTP-Statuscode (z.B. 401, 403, 429)
}
}Häufige Fehlercodes:
| Code | Status | Beschreibung |
|---|---|---|
invalid_credentials | 401 | Falsches E-Mail oder Passwort |
account_locked | 403 | Konto nach Fehlversuchen temporär gesperrt |
mfa_required | 403 | MFA-Challenge erforderlich — stattdessen gehosteten Login verwenden |
invalid_token | 401 | Token ist abgelaufen oder ungültig |
permission_denied | 403 | Benutzer hat nicht die erforderliche Berechtigung |
rate_limited | 429 | Zu viele Anfragen — Retry-After-Header beachten |
not_found | 404 | Ressource existiert nicht |
validation_error | 422 | Request-Body hat Validierung nicht bestanden |
Verwandte Seiten
- React SDK — React-Kontext, Hooks und Komponenten auf Basis von @auris/js
- Next.js SDK — Serverseitige Helfer und Edge Middleware für Next.js
- Hosted Login Guide — Vollständige PKCE-Flow-Anleitung
- Fine-Grained Authorization — FGA-Modell und Tuple-Verwaltung
- Webhooks — Webhook-Zustellung und HMAC-Verifizierung