Skip to Content

SDK JavaScript (@auris/js)

@auris/js v0.1.0

@auris/js è l’SDK fondamentale di Auris. È una libreria zero-dipendenze che funziona in browser, Node.js 18+, ed edge runtime (Cloudflare Workers, Vercel Edge, Deno). Sono incluse sia build ESM (import) che CJS (require), insieme a dichiarazioni TypeScript complete.

Gli SDK React e Next.js sono wrapper leggeri attorno a @auris/js. Se stai costruendo un’applicazione framework-agnostica o hai bisogno dell’API di livello più basso, usa direttamente questo pacchetto.


Installazione

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

AurisClient

AurisClient è il punto di ingresso principale. Crea un’istanza per applicazione.

Costruttore

import { AurisClient } from '@auris/js' const auris = new AurisClient({ domain: 'auth.tuodominio.com', // Dominio del tenant Auris (obbligatorio) clientId: 'app_xxxxx', // Client ID dell'applicazione dalla Console (obbligatorio) redirectUri: 'http://localhost:3000/callback', // Deve corrispondere a un Callback URL registrato (obbligatorio per i flussi PKCE) tenant: 'my-tenant', // Identificativo tenant inviato come header x-tenant (opzionale) storage: 'localStorage', // Archiviazione token: 'localStorage' | 'sessionStorage' | 'memory' | istanza TokenStore autoRefresh: true, // Aggiorna automaticamente i token di accesso prima della scadenza (default: true) scope: 'openid profile email', // Scope OAuth2 da richiedere (default: 'openid profile email') })

Opzioni di configurazione:

OpzioneTipoObbligatorioDefaultDescrizione
domainstringSì—Il dominio del tenant Auris, senza https://
clientIdstringSì—Client ID dell’applicazione dalla Console
redirectUristringCondizionale—URL di callback per i flussi PKCE. Deve essere registrato nella Console.
tenantstringNo'default'Identificativo tenant inviato come header HTTP x-tenant
storagestring | TokenStoreNo'localStorage'Dove persistere i token
autoRefreshbooleanNotrueAggiorna i token di accesso automaticamente prima della scadenza
scopestringNo'openid profile email'Scope OAuth2 separati da spazio

Negli edge runtime e negli ambienti Node.js senza localStorage, l’SDK ricade automaticamente sull’archiviazione in memoria. Passa storage: 'memory' esplicitamente se vuoi attivare questo comportamento negli ambienti browser.


Metodi di Autenticazione

loginWithRedirect(options?)

Avvia il flusso Authorization Code OAuth2 con PKCE. Genera un code verifier e un challenge, memorizza il verifier, poi reindirizza il browser alla pagina di login ospitata da Auris.

Firma:

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

Parametri:

OpzioneTipoDescrizione
login_hintstringPre-compila il campo email
prompt'login' | 'none'login forza la ri-autenticazione. none restituisce un errore se non esiste una sessione attiva.
screen_hint'signup'Apre la schermata di registrazione invece di quella di login
connectionstringForza uno specifico alias di connessione SSO
localestringImposta il locale della pagina ospitata (en, it, de, fr, es)
statestringValore state personalizzato. L’SDK genera un valore casuale sicuro se omesso.
// Login redirect base await auris.loginWithRedirect() // Apri la schermata di registrazione await auris.loginWithRedirect({ screen_hint: 'signup' }) // Pre-compila l'email e forza la ri-autenticazione await auris.loginWithRedirect({ login_hint: '[email protected]', prompt: 'login' })

handleRedirectCallback()

Completa il flusso OAuth2 PKCE dopo che l’utente torna alla tua applicazione. Legge code e state dall’URL corrente, valida lo state, scambia il codice per i token e memorizza il risultato.

Chiama questo metodo esattamente una volta nella pagina di callback quando si carica per la prima volta.

Firma:

handleRedirectCallback(): Promise<AuthResult>

Restituisce: AuthResult

const result = await auris.handleRedirectCallback() if (result.user) { console.log('Autenticato come', result.user.email) window.location.href = '/dashboard' }

login(email, password)

Autenticazione diretta email/password senza redirect. Restituisce i token immediatamente.

Firma:

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

Il login diretto invia le credenziali al server dell’applicazione. Non è consigliato per le applicazioni browser perché bypassa i vantaggi di sicurezza della pagina di login ospitata (CAPTCHA, rate limiting, rilevamento login sospetti, MFA). Usa loginWithRedirect() per l’autenticazione degli utenti finali nelle app browser.

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

signup(email, password, options?)

Registra un nuovo utente e restituisce i token immediatamente.

Firma:

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

Opzioni:

OpzioneTipoDescrizione
firstNamestringNome dell’utente
lastNamestringCognome dell’utente
usernamestringUsername (deve essere univoco nel tenant)
metadataRecord<string, unknown>Metadati utente personalizzati memorizzati nell’account
const result = await auris.signup('[email protected]', 'passwordsicura', { firstName: 'Bob', lastName: 'Smith', })

logout(options?)

Revoca il refresh token, cancella i token memorizzati e opzionalmente reindirizza il browser.

Firma:

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

Opzioni:

OpzioneTipoDescrizione
returnTostringURL a cui reindirizzare dopo il logout. Deve essere nella stessa origine del tuo redirectUri.
// Cancella i token e reindirizza alla home page await auris.logout({ returnTo: 'http://localhost:3000' }) // Cancella i token senza reindirizzare (es. in un contesto Node.js) await auris.logout()

getUser()

Restituisce l’utente attualmente autenticato dal token ID memorizzato. Restituisce null se l’utente non è autenticato.

Firma:

getUser(): Promise<UserInfo | null>

Restituisce: UserInfo | null

const user = await auris.getUser() if (user) { console.log(user.id) // ID utente Auris console.log(user.email) console.log(user.roles) // string[] — ruoli assegnati console.log(user.metadata) // Record<string, unknown> }

isAuthenticated()

Restituisce true se l’utente ha un token di accesso valido (non scaduto).

Firma:

isAuthenticated(): Promise<boolean>
if (await auris.isAuthenticated()) { // Procedi con le operazioni autenticate }

getAccessToken()

Restituisce il token di accesso corrente. Se autoRefresh è abilitato e il token è scaduto, scambia automaticamente il refresh token per un nuovo token di accesso prima di restituirlo.

Firma:

getAccessToken(): Promise<string | null>
const token = await auris.getAccessToken() // Usa il token nelle richieste API const response = await fetch('/api/data', { headers: { Authorization: `Bearer ${token}` }, })

refreshToken()

Scambia manualmente il refresh token memorizzato per una nuova coppia di token di accesso e refresh.

Firma:

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

loginWithMagicLink(email)

Invia un’email con magic link all’indirizzo specificato. L’utente clicca il link nell’email per completare l’autenticazione tramite verifyMagicLink().

Firma:

loginWithMagicLink(email: string): Promise<void>
await auris.loginWithMagicLink('[email protected]') // Reindirizza o mostra un messaggio "Controlla la tua email"

verifyMagicLink(token)

Verifica un token magic link (estratto dall’URL su cui l’utente ha cliccato). Restituisce token e informazioni utente in caso di successo.

Firma:

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

forgotPassword(email)

Invia un’email di reimpostazione password all’indirizzo specificato.

Firma:

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

loginWithSocial(provider)

Reindirizza l’utente al provider di identità social specificato. Auris gestisce il flusso OAuth del provider e restituisce l’utente al tuo redirectUri con un codice di autorizzazione.

Firma:

loginWithSocial(provider: SocialProvider): Promise<void>

Provider supportati:

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

getM2MToken(clientSecret, scopes?)

Ottiene un token di accesso machine-to-machine usando il grant OAuth2 client_credentials. Usalo per chiamate API server-to-server dove non è coinvolto nessun utente.

Firma:

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) // secondi alla scadenza

Non usare mai getM2MToken() nel codice browser. Il clientSecret deve rimanere solo lato server. Usa questo metodo nelle route API Node.js, nei worker in background e negli script CLI.


onAuthStateChange(callback)

Si iscrive ai cambiamenti dello stato di autenticazione. Il callback viene eseguito ogni volta che l’utente accede, esce, o il token viene aggiornato.

Firma:

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

Restituisce: Unsubscribe — chiamala per rimuovere il listener.

const unsubscribe = auris.onAuthStateChange((user) => { if (user) { console.log('Accesso effettuato:', user.email) } else { console.log('Disconnesso') } }) // In seguito, quando non hai più bisogno del listener: unsubscribe()

Modulo Permessi

Accessibile tramite auris.permissions. Tutti i metodi chiamano l’API Auris e richiedono che l’utente sia autenticato.

check(permissions)

Verifica se l’utente corrente ha uno o tutti i permessi specificati.

Firma:

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

Restituisce: PermissionCheckResult

interface PermissionCheckResult { has: (permission: string) => boolean hasAll: boolean // true se l'utente ha tutti i permessi nell'array hasAny: boolean // true se l'utente ha almeno un permesso nell'array results: Record<string, boolean> // mappa risultati per-permesso }
const result = await auris.permissions.check(['manage:users', 'view:reports']) if (result.has('manage:users')) { // Mostra UI admin } if (result.hasAll) { // L'utente ha entrambi i permessi }

checkOne(permission)

Verifica un singolo permesso. Restituisce true se consentito, false altrimenti.

Firma:

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

listUserPermissions()

Restituisce l’elenco completo delle stringhe di permesso assegnate all’utente corrente in tutti i suoi ruoli.

Firma:

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

Modulo FGA

Accessibile tramite auris.fga. Implementa l’autorizzazione fine-grained in stile Zanzibar. Richiede che la funzionalità FGA sia abilitata sul tenant.

check(input)

Verifica se un soggetto ha una relazione con un oggetto.

Firma:

check(input: FgaCheckInput): Promise<FgaCheckResult>
interface FgaCheckInput { objectType: string // es. 'document' objectId: string // es. 'doc_abc123' relation: string // es. 'viewer' subjectType: string // es. 'user' subjectId: string // es. l'ID dell'utente corrente } interface FgaCheckResult { allowed: boolean resolution?: ResolutionNode[] // traccia modalità explain }
const result = await auris.fga.check({ objectType: 'document', objectId: 'doc_abc123', relation: 'editor', subjectType: 'user', subjectId: user.id, }) if (result.allowed) { abilitaModalitaModifica() }

expand(input)

Espande una relazione per elencare tutti i soggetti (utenti o gruppi) che la hanno su un dato oggetto.

Firma:

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

listObjects(input)

Elenca tutti gli ID oggetto di un dato tipo su cui il soggetto ha la relazione specificata.

Firma:

listObjects(input: FgaListObjectsInput): Promise<string[]>
// Elenca tutti i documenti che l'utente corrente può visualizzare const documentIds = await auris.fga.listObjects({ objectType: 'document', relation: 'viewer', subjectType: 'user', subjectId: user.id, })

writeTuples(tuples)

Scrive una o più tuple di relazione nel store FGA.

Firma:

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

deleteTuples(tuples)

Elimina una o più tuple di relazione dallo store FGA.

Firma:

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

Client di Gestione

createManagementClient(config) crea un client per la Management API che si autentica con M2M client_credentials. Usalo nel codice backend (script Node.js, route API, strumenti CLI) per gestire il tenant a livello programmatico.

Firma:

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

Utenti

// Elenca utenti con paginazione const { users, total } = await mgmt.users.list({ page: 1, limit: 50 }) // Ottieni un singolo utente per ID const user = await mgmt.users.get('usr_abc123') // Crea un utente const newUser = await mgmt.users.create({ email: '[email protected]', password: 'password-temporanea', firstName: 'Alice', roles: ['editor'], }) // Aggiorna un utente await mgmt.users.update('usr_abc123', { firstName: 'Alicia' }) // Disabilita un utente (soft-disable — non può effettuare il login) await mgmt.users.update('usr_abc123', { enabled: false }) // Elimina un utente await mgmt.users.delete('usr_abc123')

Organizzazioni

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')

Ruoli

const roles = await mgmt.roles.list() const role = await mgmt.roles.get('role_abc') const newRole = await mgmt.roles.create({ name: 'Editor', description: 'Può modificare i contenuti' }) await mgmt.roles.update('role_abc', { description: 'Può visualizzare e modificare i contenuti' }) await mgmt.roles.delete('role_abc')

Verifica Webhook

verifyWebhookSignature(options) verifica che un webhook in ingresso sia stato inviato da Auris e non sia stato manomesso. Usa HMAC-SHA256.

Firma:

import { verifyWebhookSignature } from '@auris/js' const isValid = await verifyWebhookSignature({ payload: rawBody, // string o Buffer — il corpo grezzo della richiesta signature: headerValue, // valore dell'header X-Webhook-Signature secret: 'whsec_xxxxx', // segreto di firma dalla Console timestamp: headerTs, // valore dell'header X-Webhook-Timestamp maxAge: 300, // opzionale: rifiuta webhook più vecchi di N secondi (default: 300) })

Esempio 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: 'Firma non valida' }) } const event = JSON.parse(req.body) console.log('Evento ricevuto:', event.type) res.json({ received: true }) })

Verifica JWT

verifyJwt(token, jwksUrl) verifica un token di accesso emesso da Auris usando le chiavi pubbliche dall’endpoint JWKS. Zero dipendenze — usa la Web Crypto API nei browser e in Node.js 18+.

Firma:

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

La funzione restituisce il payload JWT decodificato se la firma è valida, oppure lancia un’eccezione se il token è scaduto, malformato o firmato con una chiave sconosciuta. I risultati del recupero chiavi sono memorizzati nella cache per 1 ora.

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

Tipi TypeScript

Tipi chiave esportati da @auris/js:

// Risultati autenticazione interface AuthResult { user: UserInfo accessToken: string refreshToken?: string expiresIn: number tokenType: 'Bearer' } // Informazioni utente 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 } // Risultato token M2M interface M2MTokenResult { accessToken: string expiresIn: number tokenType: 'Bearer' scope: string } // Risultato verifica permesso interface PermissionCheckResult { has: (permission: string) => boolean hasAll: boolean hasAny: boolean results: Record<string, boolean> } // Tipi FGA interface FgaCheckInput { objectType: string objectId: string relation: string subjectType: string subjectId: string subjectRelation?: string } interface FgaCheckResult { allowed: boolean resolution?: ResolutionNode[] } // Interfaccia adapter di archiviazione interface TokenStore { get(key: string): string | null | Promise<string | null> set(key: string, value: string): void | Promise<void> remove(key: string): void | Promise<void> } // Funzione di disiscrizione da onAuthStateChange type Unsubscribe = () => void

Adapter di Archiviazione Personalizzato

Implementa l’interfaccia TokenStore per persistere i token in qualsiasi backend di archiviazione.

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

Gestione degli Errori

Tutti i metodi async lanciano un AurisError in caso di errore.

import { AurisClient, AurisError } from '@auris/js' try { await auris.login('[email protected]', 'passworderrata') } catch (err) { if (err instanceof AurisError) { console.error(err.code) // es. 'invalid_credentials', 'account_locked', 'mfa_required' console.error(err.message) // Messaggio leggibile console.error(err.status) // Codice di stato HTTP (es. 401, 403, 429) } }

Codici di errore comuni:

CodiceStatoDescrizione
invalid_credentials401Email o password errate
account_locked403Account temporaneamente bloccato dopo tentativi falliti
mfa_required403Richiesta sfida MFA — usa il login ospitato
invalid_token401Il token è scaduto o malformato
permission_denied403L’utente non ha il permesso richiesto
rate_limited429Troppe richieste — rispetta l’header Retry-After
not_found404La risorsa non esiste
validation_error422Il corpo della richiesta non ha superato la validazione

Correlati