Skip to Content

SDK JavaScript (@auris/js)

@auris/js v0.1.0

@auris/js est le SDK fondamental d’Auris. C’est une bibliothèque zéro-dépendance qui fonctionne dans les navigateurs, Node.js 18+, et les edge runtimes (Cloudflare Workers, Vercel Edge, Deno). Les builds ESM (import) et CJS (require) sont incluses, avec des déclarations TypeScript complètes.

Les SDK React et Next.js sont des wrappers légers autour de @auris/js. Si tu construis une application agnostique au framework ou as besoin de l’API de niveau le plus bas, utilise ce package directement.


Installation

npm install @auris/js
pnpm add @auris/js
yarn add @auris/js

AurisClient

AurisClient est le point d’entrée principal. Crée une instance par application.

Constructeur

import { AurisClient } from '@auris/js' const auris = new AurisClient({ domain: 'auth.votredomaine.com', // Domaine du tenant Auris (obligatoire) clientId: 'app_xxxxx', // Client ID de l'application depuis la Console (obligatoire) redirectUri: 'http://localhost:3000/callback', // Doit correspondre à un Callback URL enregistré (obligatoire pour les flux PKCE) tenant: 'my-tenant', // Identifiant tenant envoyé comme en-tête x-tenant (optionnel) storage: 'localStorage', // Stockage des tokens : 'localStorage' | 'sessionStorage' | 'memory' | instance TokenStore autoRefresh: true, // Rafraîchit automatiquement les tokens d'accès avant expiration (défaut : true) scope: 'openid profile email', // Scopes OAuth2 à demander (défaut : 'openid profile email') })

Options de configuration :

OptionTypeObligatoireDéfautDescription
domainstringOui—Le domaine du tenant Auris, sans https://
clientIdstringOui—Client ID de l’application depuis la Console
redirectUristringConditionnel—URL de callback pour les flux PKCE. Doit être enregistré dans la Console.
tenantstringNon'default'Identifiant tenant envoyé comme en-tête HTTP x-tenant
storagestring | TokenStoreNon'localStorage'Où persister les tokens
autoRefreshbooleanNontrueRafraîchit les tokens d’accès automatiquement avant expiration
scopestringNon'openid profile email'Scopes OAuth2 séparés par des espaces

Dans les edge runtimes et les environnements Node.js sans localStorage, le SDK bascule automatiquement sur le stockage en mémoire. Passe storage: 'memory' explicitement si tu veux activer ce comportement dans les environnements navigateur.


Méthodes d’Authentification

loginWithRedirect(options?)

Lance le flux Authorization Code OAuth2 avec PKCE. Génère un code verifier et un challenge, mémorise le verifier, puis redirige le navigateur vers la page de connexion hébergée par Auris.

Signature :

loginWithRedirect(options?: LoginWithRedirectOptions): Promise<void>

Paramètres :

OptionTypeDescription
login_hintstringPré-remplit le champ email
prompt'login' | 'none'login force la ré-authentification. none retourne une erreur s’il n’existe pas de session active.
screen_hint'signup'Ouvre l’écran d’inscription au lieu de la connexion
connectionstringForce un alias de connexion SSO spécifique
localestringDéfinit la langue de la page hébergée (en, it, de, fr, es)
statestringValeur state personnalisée. Le SDK génère une valeur aléatoire sécurisée si omis.
// Redirection de connexion basique await auris.loginWithRedirect() // Ouvrir l'écran d'inscription await auris.loginWithRedirect({ screen_hint: 'signup' }) // Pré-remplir l'email et forcer la ré-authentification await auris.loginWithRedirect({ login_hint: '[email protected]', prompt: 'login' })

handleRedirectCallback()

Complète le flux OAuth2 PKCE après le retour de l’utilisateur dans ton application. Lit code et state depuis l’URL courante, valide le state, échange le code contre des tokens et mémorise le résultat.

Appelle cette méthode exactement une fois sur la page de callback lors du premier chargement.

Signature :

handleRedirectCallback(): Promise<AuthResult>

Retourne : AuthResult

const result = await auris.handleRedirectCallback() if (result.user) { console.log('Authentifié en tant que', result.user.email) window.location.href = '/dashboard' }

login(email, password)

Authentification directe email/mot de passe sans redirection. Retourne les tokens immédiatement.

Signature :

login(email: string, password: string): Promise<AuthResult>

La connexion directe envoie les identifiants au serveur de l’application. Ce n’est pas recommandé pour les applications navigateur car cela contourne les avantages de sécurité de la page de connexion hébergée (CAPTCHA, rate limiting, détection de connexions suspectes, MFA). Utilise loginWithRedirect() pour l’authentification des utilisateurs finaux dans les applications navigateur.

const result = await auris.login('[email protected]', 'hunter2') console.log(result.user.id)

signup(email, password, options?)

Inscrit un nouvel utilisateur et retourne les tokens immédiatement.

Signature :

signup(email: string, password: string, options?: SignupOptions): Promise<AuthResult>

Options :

OptionTypeDescription
firstNamestringPrénom de l’utilisateur
lastNamestringNom de famille de l’utilisateur
usernamestringNom d’utilisateur (doit être unique dans le tenant)
metadataRecord<string, unknown>Métadonnées utilisateur personnalisées stockées dans le compte
const result = await auris.signup('[email protected]', 'motdepassesécurisé', { firstName: 'Bob', lastName: 'Smith', })

logout(options?)

Révoque le refresh token, supprime les tokens mémorisés et redirige optionnellement le navigateur.

Signature :

logout(options?: LogoutOptions): Promise<void>

Options :

OptionTypeDescription
returnTostringURL vers laquelle rediriger après la déconnexion. Doit être dans la même origine que ton redirectUri.
// Supprime les tokens et redirige vers la page d'accueil await auris.logout({ returnTo: 'http://localhost:3000' }) // Supprime les tokens sans rediriger (ex. dans un contexte Node.js) await auris.logout()

getUser()

Retourne l’utilisateur actuellement authentifié depuis le token ID mémorisé. Retourne null si l’utilisateur n’est pas authentifié.

Signature :

getUser(): Promise<UserInfo | null>

Retourne : UserInfo | null

const user = await auris.getUser() if (user) { console.log(user.id) // ID utilisateur Auris console.log(user.email) console.log(user.roles) // string[] — rôles assignés console.log(user.metadata) // Record<string, unknown> }

isAuthenticated()

Retourne true si l’utilisateur a un token d’accès valide (non expiré).

Signature :

isAuthenticated(): Promise<boolean>
if (await auris.isAuthenticated()) { // Procéder aux opérations authentifiées }

getAccessToken()

Retourne le token d’accès courant. Si autoRefresh est activé et que le token est expiré, échange automatiquement le refresh token pour un nouveau token d’accès avant de le retourner.

Signature :

getAccessToken(): Promise<string | null>
const token = await auris.getAccessToken() // Utiliser le token dans les requêtes API const response = await fetch('/api/data', { headers: { Authorization: `Bearer ${token}` }, })

refreshToken()

Échange manuellement le refresh token mémorisé pour une nouvelle paire de tokens d’accès et de rafraîchissement.

Signature :

refreshToken(): Promise<AuthResult>
const result = await auris.refreshToken() console.log(result.accessToken)

loginWithMagicLink(email)

Envoie un email avec magic link à l’adresse spécifiée. L’utilisateur clique le lien dans l’email pour compléter l’authentification via verifyMagicLink().

Signature :

loginWithMagicLink(email: string): Promise<void>
await auris.loginWithMagicLink('[email protected]') // Redirige ou affiche un message "Vérifie ton email"

verifyMagicLink(token)

Vérifie un token magic link (extrait de l’URL sur laquelle l’utilisateur a cliqué). Retourne les tokens et les informations utilisateur en cas de succès.

Signature :

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('Authentifié :', result.user) }

forgotPassword(email)

Envoie un email de réinitialisation de mot de passe à l’adresse spécifiée.

Signature :

forgotPassword(email: string): Promise<void>
await auris.forgotPassword('[email protected]')

loginWithSocial(provider)

Redirige l’utilisateur vers le provider d’identité social spécifié. Auris gère le flux OAuth du provider et retourne l’utilisateur à ton redirectUri avec un code d’autorisation.

Signature :

loginWithSocial(provider: SocialProvider): Promise<void>

Providers supportés :

type SocialProvider = | 'google' | 'github' | 'microsoft' | 'apple' | 'facebook' | 'discord' | 'linkedin' | 'twitter' | 'slack'
await auris.loginWithSocial('google') await auris.loginWithSocial('github')

getM2MToken(clientSecret, scopes?)

Obtient un token d’accès machine-to-machine en utilisant le grant OAuth2 client_credentials. Utilise-le pour les appels API serveur-à-serveur où aucun utilisateur n’est impliqué.

Signature :

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) // secondes avant expiration

N’utilise jamais getM2MToken() dans le code navigateur. Le clientSecret doit rester côté serveur uniquement. Utilise cette méthode dans les routes API Node.js, les workers en arrière-plan et les scripts CLI.


onAuthStateChange(callback)

S’abonne aux changements d’état d’authentification. Le callback est exécuté chaque fois que l’utilisateur se connecte, se déconnecte, ou que le token est rafraîchi.

Signature :

onAuthStateChange(callback: (user: UserInfo | null) => void): Unsubscribe

Retourne : Unsubscribe — appelle-la pour supprimer le listener.

const unsubscribe = auris.onAuthStateChange((user) => { if (user) { console.log('Connecté :', user.email) } else { console.log('Déconnecté') } }) // Plus tard, quand tu n'as plus besoin du listener : unsubscribe()

Module Permissions

Accessible via auris.permissions. Toutes les méthodes appellent l’API Auris et nécessitent que l’utilisateur soit authentifié.

check(permissions)

Vérifie si l’utilisateur courant a un ou tous les permissions spécifiés.

Signature :

check(permissions: string[]): Promise<PermissionCheckResult>

Retourne : PermissionCheckResult

interface PermissionCheckResult { has: (permission: string) => boolean hasAll: boolean // true si l'utilisateur a tous les permissions dans le tableau hasAny: boolean // true si l'utilisateur a au moins un permission dans le tableau results: Record<string, boolean> // carte des résultats par permission }
const result = await auris.permissions.check(['manage:users', 'view:reports']) if (result.has('manage:users')) { // Afficher l'UI admin } if (result.hasAll) { // L'utilisateur a les deux permissions }

checkOne(permission)

Vérifie un seul permission. Retourne true si autorisé, false sinon.

Signature :

checkOne(permission: string): Promise<boolean>
const peutSupprimer = await auris.permissions.checkOne('delete:documents') if (peutSupprimer) { afficherBoutonSupprimer() }

listUserPermissions()

Retourne la liste complète des chaînes de permission assignées à l’utilisateur courant dans tous ses rôles.

Signature :

listUserPermissions(): Promise<string[]>
const permissions = await auris.permissions.listUserPermissions() console.log(permissions) // ['view:documents', 'create:documents', 'manage:users', ...]

Module FGA

Accessible via auris.fga. Implémente l’autorisation fine-grained de style Zanzibar. Nécessite que la fonctionnalité FGA soit activée sur le tenant.

check(input)

Vérifie si un sujet a une relation avec un objet.

Signature :

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) { activerModeEdition() }

expand(input)

Développe une relation pour lister tous les sujets (utilisateurs ou groupes) qui l’ont sur un objet donné.

Signature :

expand(input: FgaExpandInput): Promise<ExpandTree>
const tree = await auris.fga.expand({ objectType: 'project', objectId: 'proj_xyz', relation: 'member', }) console.log(tree)

listObjects(input)

Liste tous les IDs d’objet d’un type donné sur lesquels le sujet a la relation spécifiée.

Signature :

listObjects(input: FgaListObjectsInput): Promise<string[]>
// Lister tous les documents que l'utilisateur courant peut voir const documentIds = await auris.fga.listObjects({ objectType: 'document', relation: 'viewer', subjectType: 'user', subjectId: user.id, })

writeTuples(tuples)

Écrit un ou plusieurs tuples de relation dans le store FGA.

Signature :

writeTuples(tuples: WriteTupleInput[]): Promise<void>
await auris.fga.writeTuples([ { objectType: 'document', objectId: 'doc_abc123', relation: 'editor', subjectType: 'user', subjectId: 'usr_456', }, ])

deleteTuples(tuples)

Supprime un ou plusieurs tuples de relation du store FGA.

Signature :

deleteTuples(tuples: WriteTupleInput[]): Promise<void>
await auris.fga.deleteTuples([ { objectType: 'document', objectId: 'doc_abc123', relation: 'editor', subjectType: 'user', subjectId: 'usr_456', }, ])

Client de Gestion

createManagementClient(config) crée un client pour la Management API qui s’authentifie avec M2M client_credentials. Utilise-le dans le code backend (scripts Node.js, routes API, outils CLI) pour gérer le tenant de manière programmatique.

Signature :

import { createManagementClient } from '@auris/js' const mgmt = await createManagementClient({ domain: 'auth.votredomaine.com', clientId: 'app_xxxxx', clientSecret: 'cs_live_xxxxx', tenant: 'my-tenant', })

Utilisateurs

// Lister les utilisateurs avec pagination const { users, total } = await mgmt.users.list({ page: 1, limit: 50 }) // Obtenir un seul utilisateur par ID const user = await mgmt.users.get('usr_abc123') // Créer un utilisateur const newUser = await mgmt.users.create({ email: '[email protected]', password: 'mot-de-passe-temporaire', firstName: 'Alice', roles: ['editor'], }) // Mettre à jour un utilisateur await mgmt.users.update('usr_abc123', { firstName: 'Alicia' }) // Désactiver un utilisateur (soft-disable — ne peut pas se connecter) await mgmt.users.update('usr_abc123', { enabled: false }) // Supprimer un utilisateur await mgmt.users.delete('usr_abc123')

Organisations

const orgs = await mgmt.organizations.list() const org = await mgmt.organizations.get('org_xyz') const newOrg = await mgmt.organizations.create({ name: 'Acme Corp', slug: 'acme' }) await mgmt.organizations.update('org_xyz', { name: 'Acme Corporation' }) await mgmt.organizations.delete('org_xyz')

Rôles

const roles = await mgmt.roles.list() const role = await mgmt.roles.get('role_abc') const newRole = await mgmt.roles.create({ name: 'Éditeur', description: 'Peut modifier les contenus' }) await mgmt.roles.update('role_abc', { description: 'Peut voir et modifier les contenus' }) await mgmt.roles.delete('role_abc')

Vérification Webhook

verifyWebhookSignature(options) vérifie qu’un webhook entrant a été envoyé par Auris et n’a pas été altéré. Utilise HMAC-SHA256.

Signature :

import { verifyWebhookSignature } from '@auris/js' const isValid = await verifyWebhookSignature({ payload: rawBody, // string ou Buffer — le corps brut de la requête signature: headerValue, // valeur de l'en-tête X-Webhook-Signature secret: 'whsec_xxxxx', // secret de signature depuis la Console timestamp: headerTs, // valeur de l'en-tête X-Webhook-Timestamp maxAge: 300, // optionnel : rejette les webhooks plus anciens que N secondes (défaut : 300) })

Exemple Node.js (Express) :

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: 'Signature invalide' }) } const event = JSON.parse(req.body) console.log('Événement reçu :', event.type) res.json({ received: true }) })

Vérification JWT

verifyJwt(token, jwksUrl) vérifie un token d’accès émis par Auris en utilisant les clés publiques depuis l’endpoint JWKS. Zéro dépendance — utilise la Web Crypto API dans les navigateurs et Node.js 18+.

Signature :

import { verifyJwt } from '@auris/js' const payload = await verifyJwt(token, 'https://auth.votredomaine.com/.well-known/jwks.json')

La fonction retourne le payload JWT décodé si la signature est valide, ou lève une exception si le token est expiré, malformé ou signé avec une clé inconnue. Les résultats de récupération des clés sont mis en cache pendant 1 heure.

import { verifyJwt } from '@auris/js' try { const payload = await verifyJwt( accessToken, `https://${process.env.AURIS_DOMAIN}/.well-known/jwks.json` ) console.log('ID Utilisateur :', payload.sub) console.log('Rôles :', payload.roles) } catch (err) { console.error('Token invalide :', err.message) }

Types TypeScript

Types clés exportés par @auris/js :

// Résultats d'authentification interface AuthResult { user: UserInfo accessToken: string refreshToken?: string expiresIn: number tokenType: 'Bearer' } // Informations utilisateur 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 } // Résultat token M2M interface M2MTokenResult { accessToken: string expiresIn: number tokenType: 'Bearer' scope: string } // Résultat vérification permission interface PermissionCheckResult { has: (permission: string) => boolean hasAll: boolean hasAny: boolean results: Record<string, boolean> } // Types FGA interface FgaCheckInput { objectType: string objectId: string relation: string subjectType: string subjectId: string subjectRelation?: string } interface FgaCheckResult { allowed: boolean resolution?: ResolutionNode[] } // Interface adaptateur de stockage interface TokenStore { get(key: string): string | null | Promise<string | null> set(key: string, value: string): void | Promise<void> remove(key: string): void | Promise<void> } // Fonction de désabonnement de onAuthStateChange type Unsubscribe = () => void

Adaptateur de Stockage Personnalisé

Implémente l’interface TokenStore pour persister les tokens dans n’importe quel backend de stockage.

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.votredomaine.com', clientId: 'app_xxxxx', storage: new RedisTokenStore(redisClient), })

Gestion des Erreurs

Toutes les méthodes async lèvent une AurisError en cas d’erreur.

import { AurisClient, AurisError } from '@auris/js' try { await auris.login('[email protected]', 'mauvaisMotDePasse') } catch (err) { if (err instanceof AurisError) { console.error(err.code) // ex. 'invalid_credentials', 'account_locked', 'mfa_required' console.error(err.message) // Message lisible console.error(err.status) // Code de statut HTTP (ex. 401, 403, 429) } }

Codes d’erreur courants :

CodeStatutDescription
invalid_credentials401Email ou mot de passe incorrect
account_locked403Compte temporairement bloqué après des tentatives échouées
mfa_required403Défi MFA requis — utilise la connexion hébergée
invalid_token401Le token est expiré ou malformé
permission_denied403L’utilisateur n’a pas le permission requis
rate_limited429Trop de requêtes — respecte l’en-tête Retry-After
not_found404La ressource n’existe pas
validation_error422Le corps de la requête n’a pas passé la validation

Corrélés