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/jspnpm add @auris/jsyarn add @auris/jsAurisClient
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 :
| Option | Type | Obligatoire | Défaut | Description |
|---|---|---|---|---|
domain | string | Oui | — | Le domaine du tenant Auris, sans https:// |
clientId | string | Oui | — | Client ID de l’application depuis la Console |
redirectUri | string | Conditionnel | — | URL de callback pour les flux PKCE. Doit être enregistré dans la Console. |
tenant | string | Non | 'default' | Identifiant tenant envoyé comme en-tête HTTP x-tenant |
storage | string | TokenStore | Non | 'localStorage' | Où persister les tokens |
autoRefresh | boolean | Non | true | Rafraîchit les tokens d’accès automatiquement avant expiration |
scope | string | Non | '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 :
| Option | Type | Description |
|---|---|---|
login_hint | string | Pré-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 |
connection | string | Force un alias de connexion SSO spécifique |
locale | string | Définit la langue de la page hébergée (en, it, de, fr, es) |
state | string | Valeur 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 :
| Option | Type | Description |
|---|---|---|
firstName | string | Prénom de l’utilisateur |
lastName | string | Nom de famille de l’utilisateur |
username | string | Nom d’utilisateur (doit être unique dans le tenant) |
metadata | Record<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 :
| Option | Type | Description |
|---|---|---|
returnTo | string | URL 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 expirationN’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): UnsubscribeRetourne : 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 = () => voidAdaptateur 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 :
| Code | Statut | Description |
|---|---|---|
invalid_credentials | 401 | Email ou mot de passe incorrect |
account_locked | 403 | Compte temporairement bloqué après des tentatives échouées |
mfa_required | 403 | Défi MFA requis — utilise la connexion hébergée |
invalid_token | 401 | Le token est expiré ou malformé |
permission_denied | 403 | L’utilisateur n’a pas le permission requis |
rate_limited | 429 | Trop de requêtes — respecte l’en-tête Retry-After |
not_found | 404 | La ressource n’existe pas |
validation_error | 422 | Le corps de la requête n’a pas passé la validation |
Corrélés
- SDK React — Contexte React, hooks et composants construits sur @auris/js
- SDK Next.js — Helpers côté serveur et Edge Middleware pour Next.js
- Guide Connexion Hébergée — Procédure complète du flux PKCE
- Autorisation Fine-Grained — Modèle FGA et gestion des tuples
- Webhooks — Livraison de webhooks et vérification HMAC