Sign in with Dazr Identity: documentazione per sviluppatori

Le persone possono già usare il loro account Google o Microsoft dentro Dazr Identity, quindi alla tua app non servono pulsanti Google e Microsoft separati accanto: un pulsante invece di tre.

Discovery ed endpoint

Tutto è descritto nel documento di discovery. Indica l’issuer alla tua libreria e lei troverà il resto.

CosaIndirizzo
Issuerhttps://identity.dazr.eu
Discoveryhttps://identity.dazr.eu/.well-known/openid-configuration
Autorizzazionehttps://identity.dazr.eu/oauth/authorize
Tokenhttps://identity.dazr.eu/oauth/token
Informazioni utentehttps://identity.dazr.eu/oauth/userinfo
Chiavi pubbliche (JWKS)https://identity.dazr.eu/oauth/jwks
Revoca (RFC 7009)https://identity.dazr.eu/oauth/revoke
Introspezione (RFC 7662), solo app web serverhttps://identity.dazr.eu/oauth/introspect
Disconnessione (RP-initiated logout)https://identity.dazr.eu/oauth/logout

Registrare un’app

Guide all’integrazione

Ogni stack qui sotto usa il proprio supporto standard per OpenID Connect. Ti servono tre valori dalla console: il client ID, il client secret (solo per le app web server) e l’URI di reindirizzamento che hai registrato. Il resto arriva dal documento di discovery.

Auth.js / NextAuth

Auth.js (NextAuth.js v5) accetta un oggetto provider OpenID Connect personalizzato. Registra un’app web server, imposta AUTH_SECRET, AUTH_DAZR_ID e AUTH_DAZR_SECRET e usa questo URL di callback come URI di reindirizzamento: https://app.example.eu/api/auth/callback/dazr.

// auth.ts
import NextAuth from "next-auth"

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [
    {
      id: "dazr",
      name: "Dazr Identity",
      type: "oidc",
      issuer: "https://identity.dazr.eu",
      clientId: process.env.AUTH_DAZR_ID,
      clientSecret: process.env.AUTH_DAZR_SECRET,
      authorization: { params: { scope: "openid profile email" } },
      checks: ["pkce", "state", "nonce"],
      client: { id_token_signed_response_alg: "ES256" },
    },
  ],
})

NextAuth.js v4 funziona allo stesso modo, con type: "oauth" e l’URL di discovery:

// pages/api/auth/[...nextauth].ts (NextAuth.js v4), in providers: [ ... ]
{
  id: "dazr",
  name: "Dazr Identity",
  type: "oauth",
  wellKnown: "https://identity.dazr.eu/.well-known/openid-configuration",
  clientId: process.env.DAZR_CLIENT_ID,
  clientSecret: process.env.DAZR_CLIENT_SECRET,
  authorization: { params: { scope: "openid profile email" } },
  idToken: true,
  checks: ["pkce", "state"],
  client: { id_token_signed_response_alg: "ES256" },
  profile(profile) {
    return { id: profile.sub, name: profile.name ?? null, email: profile.email }
  },
}

Next.js App Router

Con il file auth.ts qui sopra, aggiungi il route handler e un pulsante di accesso che esegue una server action.

// app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth"
export const { GET, POST } = handlers

// app/page.tsx
import { auth, signIn, signOut } from "@/auth"

export default async function Page() {
  const session = await auth()
  if (session?.user) {
    return (
      <form action={async () => { "use server"; await signOut() }}>
        <p>Signed in as {session.user.email}</p>
        <button type="submit">Sign out</button>
      </form>
    )
  }
  return (
    <form action={async () => { "use server"; await signIn("dazr") }}>
      <button type="submit" className="dazr-signin">Sign in with Dazr Identity</button>
    </form>
  )
}

Dai al pulsante lo stile mostrato in Il pulsante. Nelle callback, il sub di Dazr è account.providerAccountId.

WordPress

Usa un plugin client OpenID Connect generico, come OpenID Connect Generic Client. Registra un’app web server e compila le impostazioni del plugin con i valori qui sotto. Il plugin mostra l’URI di reindirizzamento da registrare nella sua pagina delle impostazioni; di default è https://example.com/wp-admin/admin-ajax.php?action=openid-connect-authorize.

ImpostazioneValore
Client IDil tuo client ID
Client secretil tuo client secret
Scopeopenid profile email
Endpoint di login (autorizzazione)https://identity.dazr.eu/oauth/authorize
Endpoint dei tokenhttps://identity.dazr.eu/oauth/token
Endpoint userinfohttps://identity.dazr.eu/oauth/userinfo
Endpoint di fine sessionehttps://identity.dazr.eu/oauth/logout
Identity key (chiave d’identità)sub
PKCEattivo (S256)

I nomi delle impostazioni variano un po’ da plugin a plugin. Se un plugin non ha l’opzione PKCE, scegline un altro: Dazr Identity rifiuta gli accessi senza PKCE.

Laravel

Laravel Socialite non ha un driver OpenID Connect generico integrato, quindi aggiungi un piccolo driver personalizzato. Manda le persone a Dazr con PKCE e legge l’utente dall’endpoint userinfo. Socialite non legge il documento di discovery, per questo gli endpoint sono scritti per esteso. Registra un’app web server con l’URI di reindirizzamento https://app.example.eu/auth/dazr/callback.

<?php
// app/Socialite/DazrProvider.php
namespace App\Socialite;

use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\User;

class DazrProvider extends AbstractProvider
{
    protected $scopes = ['openid', 'profile', 'email'];
    protected $scopeSeparator = ' ';
    protected $usesPKCE = true;

    protected function getAuthUrl($state)
    {
        return $this->buildAuthUrlFromBase('https://identity.dazr.eu/oauth/authorize', $state);
    }

    protected function getTokenUrl()
    {
        return 'https://identity.dazr.eu/oauth/token';
    }

    protected function getUserByToken($token)
    {
        $response = $this->getHttpClient()->get('https://identity.dazr.eu/oauth/userinfo', [
            'headers' => ['Authorization' => 'Bearer '.$token],
        ]);

        return json_decode((string) $response->getBody(), true);
    }

    protected function mapUserToObject(array $user)
    {
        return (new User)->setRaw($user)->map([
            'id' => $user['sub'],
            'name' => $user['name'] ?? null,
            'email' => $user['email'] ?? null,
        ]);
    }
}
// config/services.php
'dazr' => [
    'client_id' => env('DAZR_CLIENT_ID'),
    'client_secret' => env('DAZR_CLIENT_SECRET'),
    'redirect' => env('DAZR_REDIRECT_URI'),
],

// app/Providers/AppServiceProvider.php, in boot()
use Laravel\Socialite\Facades\Socialite;
use App\Socialite\DazrProvider;

Socialite::extend('dazr', function ($app) {
    return Socialite::buildProvider(DazrProvider::class, config('services.dazr'));
});

// routes/web.php
Route::get('/auth/dazr', fn () => Socialite::driver('dazr')->redirect());
Route::get('/auth/dazr/callback', function () {
    $dazr = Socialite::driver('dazr')->user();
    $user = \App\Models\User::updateOrCreate(
        ['dazr_sub' => $dazr->getId()],
        ['name' => $dazr->getName() ?? $dazr->getEmail(), 'email' => $dazr->getEmail()],
    );
    Auth::login($user);
    return redirect('/');
});

Supabase

Supabase Auth non ha un provider OpenID Connect generico da puntare su un issuer qualsiasi: i provider di accesso e le integrazioni di autenticazione di terze parti sono elenchi fissi. Quindi oggi non puoi aggiungere Dazr Identity nella dashboard di Supabase. Se Supabase aggiungerà il supporto OpenID Connect generico, usa i valori della checklist qui sotto.

L’alternativa: fai accedere le persone con Dazr Identity sul tuo server (con una delle guide di questa pagina), salva il sub di Dazr nella tabella degli utenti e comunica con Supabase da quel server con la service role key, controllando gli accessi nel tuo codice. Non inviare mai la service role key a un browser.

Django

Usa mozilla-django-oidc. Registra un’app web server con l’URI di reindirizzamento https://app.example.eu/oidc/callback/. La libreria non legge il documento di discovery, per questo gli endpoint sono scritti per esteso.

# settings.py
import os

INSTALLED_APPS += ["mozilla_django_oidc"]  # after django.contrib.auth
AUTHENTICATION_BACKENDS = [
    "mozilla_django_oidc.auth.OIDCAuthenticationBackend",
    "django.contrib.auth.backends.ModelBackend",
]

OIDC_RP_CLIENT_ID = os.environ["DAZR_CLIENT_ID"]
OIDC_RP_CLIENT_SECRET = os.environ["DAZR_CLIENT_SECRET"]
OIDC_RP_SCOPES = "openid profile email"
OIDC_RP_SIGN_ALGO = "ES256"
OIDC_OP_JWKS_ENDPOINT = "https://identity.dazr.eu/oauth/jwks"
OIDC_OP_AUTHORIZATION_ENDPOINT = "https://identity.dazr.eu/oauth/authorize"
OIDC_OP_TOKEN_ENDPOINT = "https://identity.dazr.eu/oauth/token"
OIDC_OP_USER_ENDPOINT = "https://identity.dazr.eu/oauth/userinfo"
OIDC_USE_PKCE = True
OIDC_PKCE_CODE_CHALLENGE_METHOD = "S256"

LOGIN_REDIRECT_URL = "/"
LOGOUT_REDIRECT_URL = "/"

# urls.py
from django.urls import include, path
urlpatterns += [path("oidc/", include("mozilla_django_oidc.urls"))]

# template: start the sign-in
# <a href="{% url 'oidc_authentication_init' %}">Sign in with Dazr Identity</a>

Di default il backend abbina gli utenti per email. Per collegare gli account a sub, crea una sottoclasse di OIDCAuthenticationBackend e sovrascrivi filter_users_by_claims e create_user. Usa una versione recente: le versioni più vecchie non verificano le firme ES256.

Node.js (openid-client)

openid-client (versione 6) legge il documento di discovery e verifica per te PKCE, state, nonce e l’ID token.

import * as client from 'openid-client';

const config = await client.discovery(
  new URL('https://identity.dazr.eu'),
  process.env.DAZR_CLIENT_ID,
  process.env.DAZR_CLIENT_SECRET, // public client: pass undefined here and client.None() as the 4th argument
);
const redirect_uri = 'https://app.example.eu/auth/dazr/callback';

// 1. Start: keep the three random values in the user's session.
export async function start(session) {
  session.verifier = client.randomPKCECodeVerifier();
  session.state = client.randomState();
  session.nonce = client.randomNonce();
  return client.buildAuthorizationUrl(config, {
    redirect_uri,
    scope: 'openid profile email',
    code_challenge: await client.calculatePKCECodeChallenge(session.verifier),
    code_challenge_method: 'S256',
    state: session.state,
    nonce: session.nonce,
  });
}

// 2. Callback: pass the full callback URL (a URL object).
export async function callback(session, currentUrl) {
  const tokens = await client.authorizationCodeGrant(config, currentUrl, {
    pkceCodeVerifier: session.verifier,
    expectedState: session.state,
    expectedNonce: session.nonce,
  });
  const claims = tokens.claims(); // sub, email, name
  return { sub: claims.sub, email: claims.email, name: claims.name };
}

Qualsiasi libreria OpenID Connect

Se il tuo stack non è nell’elenco, funziona qualsiasi client OpenID Connect. Controlla queste impostazioni:

Il flusso

  1. Crea un code_verifier casuale (da 43 a 128 caratteri) e la sua code_challenge = base64url(SHA-256(verifier)). Crea uno state e un nonce casuali. Conserva tutti e tre nella sessione dell’utente.
  2. Reindirizza all’endpoint di autorizzazione con response_type=code, client_id, redirect_uri, scope (sempre con openid), state, nonce, code_challenge e code_challenge_method=S256.
  3. La persona accede se necessario e vede la schermata di consenso con i dati reali. Se approva, torna al tuo URI di reindirizzamento con code, state e iss. Controlla che state corrisponda e che iss sia https://identity.dazr.eu.
  4. Sul tuo server, invia un POST all’endpoint dei token con grant_type=authorization_code, code, lo stesso redirect_uri e il code_verifier.
  5. Verifica l’ID token: firma ES256 con una chiave del JWKS (in base al kid), iss, aud = il tuo client ID, exp e il tuo nonce. Usa sub come chiave dell’account.

Il parametro prompt accetta none (risposta immediata con login_required o consent_required se la persona dovrebbe intervenire), login (chiedere alla persona di accedere di nuovo) e consent (mostrare la schermata di consenso anche se era già stata approvata). max_age è supportato. Consenso memorizzato: se la persona ha già approvato gli stessi scope, torna subito alla tua app. Se in seguito chiedi di più, la schermata di consenso mostra solo le novità.

Scope e claim

Chiedi solo ciò che ti serve. Al di fuori di questa tabella non esiste nulla: niente contatti, niente file, niente password.

ScopeClaim
openid (obbligatorio)sub: un ID casuale per la persona, uguale per ogni app della tua organizzazione e diverso per ogni altra organizzazione
profilename (se impostato) e locale
emailemail ed email_verified (sempre true)
addressaddress (formatted, street_address, locality, region, postal_code, country), solo se la persona ne ha salvato uno
organisationsorganisations: le organizzazioni che la persona seleziona nella schermata di consenso, ciascuna con id, name, country, register_number, vat, vat_verified (true solo se il servizio UE VIES ha confermato la partita IVA), verified, verification (vedi Organizzazioni verificate) e role
offline_accessnessun claim; ricevi anche un refresh token

I claim compaiono nell’ID token per gli scope approvati dalla persona. L’endpoint delle informazioni utente restituisce lo stesso insieme, con i valori attuali.

Organizzazioni verificate

Dazr verifica un’organizzazione quando il suo amministratore, o un’altra persona che può firmare per essa, firma una breve dichiarazione con una firma elettronica qualificata (QES). È immediato e funziona in tutti i paesi UE. Senza firma qualificata, il rappresentante può inviare invece una visura camerale e un documento d’identità; Dazr li controlla a mano. Ogni organizzazione nella claim organisations riporta la sua verifica attuale:

verification.statusSignificato
unverifiedNon verificata, oppure una verifica non è riuscita, è scaduta o è stata revocata (per esempio dopo una modifica della ragione sociale o del numero di registro).
pendingLa verifica è in corso: al rappresentante è stato chiesto di firmare, oppure Dazr sta controllando i documenti.
verifiedVerificata. method è qes, qes_org (il certificato stesso indica l’organizzazione, tramite partita IVA o numero di registro), documents o extract, e verified_at è un tempo Unix.

Il booleano verified resta per compatibilità ed è uguale a verification.status === 'verified'. Ogni organizzazione ha anche un id, lo stesso usato dai webhook.

"organisations": [{
  "id": "org_3k9x2m0q8w1v5t7a", "name": "Conti Logistica S.r.l.", "country": "IT",
  "register_number": "REA MI1234567", "vat": "IT12345678903", "vat_verified": true,
  "verified": false, "verification": { "status": "pending", "method": "qes" }, "role": "owner"
}]

Richiedere un’organizzazione verificata

Nella console imposta Richiedi un’organizzazione verificata su Verifica avviata o Verificata, oppure chiedilo per singola richiesta con acr_values=urn:dazr:org:verification-started o acr_values=urn:dazr:org:verified (vale la più rigorosa delle due). La tua app deve anche richiedere lo scope organisations.

Chi non ha un’organizzazione idonea la completa nello stesso accesso: il nome, l’organizzazione (con la partita IVA controllata in VIES), poi la verifica. Può firmare subito, farsi inviare la dichiarazione per email o indicare un’altra persona che firma. Poi seleziona l’organizzazione nella schermata di consenso (si possono selezionare solo organizzazioni idonee) e torna al tuo URI di reindirizzamento.

Se deve ancora firmare qualcun altro, la persona torna con stato pending, anche se hai chiesto Verificata: ricevi un codice, la claim dice pending e l’acr dell’ID token è urn:dazr:org:verification-started invece di urn:dazr:org:verified. Decidi sempre in base a verification.status, mai sul fatto che l’accesso sia riuscito. Con prompt=none ricevi interaction_required quando il requisito non è soddisfatto.

Le modifiche all’impostazione valgono dal prossimo accesso. Chi ha già effettuato l’accesso non viene disconnesso: le risposte di refresh, l’endpoint userinfo e i webhook riportano sempre lo stato attuale, quindi usali per reagire alle sessioni esistenti.

Webhook

Aggiungi un URL del webhook (https) nella console. Vedi il segreto di firma una sola volta; puoi sostituirlo. Dazr invia organisation.verification.updated quando un’organizzazione che uno dei tuoi utenti ha condiviso con la tua app diventa pending, verified, failed o unverified. Le app che non hanno mai ricevuto un’organizzazione tramite consenso non ne sanno nulla.

POST /your/webhook
Content-Type: application/json
Dazr-Event: organisation.verification.updated
Dazr-Delivery: dlv_8Fq2…
Dazr-Signature: t=1791021600,v1=5e0c…

{ "id": "evt_…", "type": "organisation.verification.updated", "created": 1791021600,
  "data": { "organisation": { "id": "org_3k9x2m0q8w1v5t7a", "name": "Conti Logistica S.r.l.", "country": "IT" },
            "status": "verified", "method": "qes_org", "verified_at": 1791021598,
            "subjects": ["Xo1c…"] } }

status è pending, verified, failed o unverified. subjects sono i valori sub, nella tua app, delle persone che hanno condiviso questa organizzazione con essa. Controlla la firma prima di fidarti del contenuto:

import crypto from 'node:crypto';
// raw = the request body exactly as received (a string), header = the Dazr-Signature header
function verifyDazrSignature(raw, header, secret) {
  const m = /^t=(\d+),v1=([a-f0-9]{64})$/.exec(header || '');
  if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false; // reject old deliveries
  const want = crypto.createHmac('sha256', secret).update(m[1] + '.' + raw).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(want), Buffer.from(m[2]));
}

Rispondi con un 2xx entro 8 secondi. Altrimenti Dazr riprova dopo circa 5 minuti, 30 minuti, 2, 6, 12 e 24 ore, poi segna la consegna come non riuscita. Ogni tentativo ha lo stesso ID Dazr-Delivery, quindi ignora i duplicati. La console elenca le consegne recenti, può reinviarne una e può inviare un evento di prova (webhook.test). Funziona anche interrogare periodicamente l’endpoint userinfo.

Token e durata

TokenDurata e regole
Codice di autorizzazione60 secondi, monouso, legato al tuo client, all’URI di reindirizzamento e alla challenge PKCE. Usare un codice due volte revoca i token che ha generato.
Access token10 minuti. Un JWT firmato (ES256, typ at+jwt) con aud = il tuo client ID. Invialo come Authorization: Bearer.
ID token10 minuti. ES256, con iss, sub, aud, exp, iat, auth_time, nonce e amr quando noto.
Refresh tokenSolo con offline_access. Cambia a ogni utilizzo: salva sempre quello nuovo. Inviare di nuovo un vecchio refresh token revoca l’intero accesso. Scade dopo 30 giorni di inutilizzo e al massimo dopo 180 giorni.

Le chiavi di firma vengono sostituite. Scegli sempre la chiave in base al kid dal JWKS e ricarica il JWKS quando trovi un kid sconosciuto.

Errori

Se client ID e URI di reindirizzamento sono validi, gli errori tornano al tuo URI di reindirizzamento come error, error_description, state e iss: per esempio invalid_request (come PKCE mancante o plain), invalid_scope, unsupported_response_type, access_denied (la persona ha annullato, oppure l’app è in test e la persona non è un membro), login_required, consent_required e interaction_required (con prompt=none, quando manca un’organizzazione verificata richiesta). Con un client sconosciuto o un URI di reindirizzamento non registrato, Dazr mostra una pagina di errore e non reindirizza mai. L’endpoint dei token risponde con errori JSON come invalid_client, invalid_grant e unsupported_grant_type.

Disconnessione

Per disconnettere qualcuno, invialo all’endpoint di disconnessione con id_token_hint (o client_id), un eventuale post_logout_redirect_uri registrato nelle impostazioni dell’app e state. Dazr chiede se vuole uscire anche da Dazr Identity su quel dispositivo, poi lo rimanda indietro. Revoca all’endpoint di revoca i refresh token che non ti servono più.

Test e messa online

Una nuova app è in fase di test: possono accedere solo i membri della tua organizzazione e la schermata di consenso lo indica. Per andare online, fai verificare la tua organizzazione in Dazr Identity, aggiungi un URI di reindirizzamento https:// e richiedi una revisione nella console. Modificare nome, finalità, informativa privacy o dati di un’app online richiede una nuova revisione.

Il pulsante

Usa il testo "Sign in with Dazr Identity" e il logo Dazr come qui sotto. Puoi modificarne le dimensioni, non il logo, i colori o il testo. Collegalo a una tua route che avvia il flusso.

<a href="/auth/dazr" style="display:inline-flex;align-items:center;gap:10px;height:44px;padding:0 18px;border-radius:22px;background:#18203a;color:#fff;font:600 15px/1 system-ui,sans-serif;text-decoration:none">
  <svg width="20" height="20" viewBox="0 0 100 100" aria-hidden="true"><path d="M50 4 89 16v31c0 25.5-16.8 42.5-39 50C27.8 89.5 11 72.5 11 47V16z" fill="#fff"/><path d="M50 15.5 79 24.5v22.8c0 19.5-12.4 32.6-29 38.7C33.4 79.9 21 66.8 21 47.3V24.5z" fill="#18203a"/><path d="M50 24 71 30.6v16.9c0 14.5-9 24.4-21 29.2-12-4.8-21-14.7-21-29.2V30.6z" fill="#fff"/></svg>
  Sign in with Dazr Identity
</a>

Un esempio minimo in Node.js

Node 18 o successivo, senza dipendenze. Un’app web server con client secret; per un client pubblico, togli l’header Authorization e invia client_id nel corpo.

import crypto from 'node:crypto';
const issuer = 'https://identity.dazr.eu';
const clientId = process.env.DAZR_CLIENT_ID;
const clientSecret = process.env.DAZR_CLIENT_SECRET;
const redirectUri = 'https://app.example.eu/auth/dazr/callback';
const b64url = (buf) => Buffer.from(buf).toString('base64url');

// 1. Start: keep verifier, state and nonce in the user's session.
export function start(session) {
  session.verifier = b64url(crypto.randomBytes(32));
  session.state = b64url(crypto.randomBytes(16));
  session.nonce = b64url(crypto.randomBytes(16));
  const challenge = b64url(crypto.createHash('sha256').update(session.verifier).digest());
  return issuer + '/oauth/authorize?' + new URLSearchParams({
    response_type: 'code', client_id: clientId, redirect_uri: redirectUri,
    scope: 'openid profile email', state: session.state, nonce: session.nonce,
    code_challenge: challenge, code_challenge_method: 'S256',
  });
}

// 2. Callback: check state, exchange the code, verify the ID token.
export async function callback(session, query) {
  if (query.error) throw new Error('sign-in failed: ' + query.error);
  if (query.state !== session.state || query.iss !== issuer) throw new Error('state or issuer mismatch');
  const res = await fetch(issuer + '/oauth/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      Authorization: 'Basic ' + Buffer.from(clientId + ':' + clientSecret).toString('base64'),
    },
    body: new URLSearchParams({ grant_type: 'authorization_code', code: query.code, redirect_uri: redirectUri, code_verifier: session.verifier }),
  });
  const tokens = await res.json();
  if (!res.ok) throw new Error(tokens.error);
  const claims = await verifyIdToken(tokens.id_token, session.nonce);
  return { sub: claims.sub, email: claims.email, name: claims.name, tokens };
}

async function verifyIdToken(idToken, nonce) {
  const [h, p, s] = idToken.split('.');
  const header = JSON.parse(Buffer.from(h, 'base64url'));
  const { keys } = await (await fetch(issuer + '/oauth/jwks')).json();
  const jwk = keys.find((k) => k.kid === header.kid);
  if (!jwk || header.alg !== 'ES256') throw new Error('unknown signing key');
  const ok = crypto.verify('sha256', Buffer.from(h + '.' + p),
    { key: crypto.createPublicKey({ key: jwk, format: 'jwk' }), dsaEncoding: 'ieee-p1363' }, Buffer.from(s, 'base64url'));
  const c = JSON.parse(Buffer.from(p, 'base64url'));
  const now = Math.floor(Date.now() / 1000);
  if (!ok || c.iss !== issuer || c.aud !== clientId || c.exp < now - 30 || c.nonce !== nonce) throw new Error('invalid ID token');
  return c;
}

Limiti

Gli endpoint di autorizzazione e dei token hanno un limite di richieste. Se ricevi HTTP 429, attendi e riprova; non riprovare in un ciclo continuo.

I tuoi obblighi

La tua organizzazione è titolare autonomo del trattamento dei dati che riceve. Le Condizioni per sviluppatori di Dazr Identity stabiliscono cosa puoi farne, come proteggerli e come segnalare le violazioni. Domande: hello@dazr.eu.