> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Inici ràpid de JavaScript per a l'autenticació

> Connecta una aplicació de Didit amb inici de sessió allotjat i PKCE: validació de callback, comprovació de sessions i tancament de sessió.

> [!WARNING]
>
> Authentication és nou: utilitza aquest exemple de flux allotjat amb una aplicació que tingui Authentication activat. El paquet `@didit-protocol/auth` encara no està publicat; l'API del paquet que hi ha a continuació és una versió preliminar, no un inici ràpid instal·lable.

## Configura l'inici de sessió allotjat

Registra la URL de callback exacta i el teu origen web per a la teva aplicació de sandbox. Copia el seu origen d'inici de sessió (`https://<slug>.sandbox.auth.didit.me`) des de la consola, tal com s'explica a la [visió general](https://docs.didit.me/ca/authentication/overview.md). Aquest exemple utilitza les APIs de criptografia del navegador i requereix HTTPS, o localhost en sandbox: consulta [desenvolupament local](https://docs.didit.me/ca/authentication/overview.md#desenvolupament-en-local) per saber què has de registrar.

L'aplicació és responsable de `state` i del verificador PKCE. L'inici de sessió allotjat s'encarrega de les pantalles de contrasenya, correu electrònic, passkey, telèfon, SSO i MFA quan es requereix. No s'ha d'incloure cap clau d'API en aquest codi.

```javascript auth.js theme={null}
// Replace both values with your registered application configuration.
const AUTH_BASE = "https://YOUR_SLUG.sandbox.auth.didit.me/";
const REDIRECT_URI = "https://YOUR_APP_ORIGIN/auth/callback";
const PENDING = "didit.auth.pending";
let tokens = null;

function base64url(bytes) {
  return btoa(String.fromCharCode(...bytes))
    .replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}

export async function signIn() {
  const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
  const state = base64url(crypto.getRandomValues(new Uint8Array(32)));
  const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
  sessionStorage.setItem(PENDING, JSON.stringify({ verifier, state, startedAt: Date.now() }));
  const url = new URL("sign-in", AUTH_BASE);
  url.search = new URLSearchParams({
    redirect_uri: REDIRECT_URI,
    state,
    code_challenge: base64url(new Uint8Array(digest)),
    code_challenge_method: "S256",
  }).toString();
  window.location.assign(url.href);
}

export async function handleCallback() {
  const query = new URLSearchParams(window.location.search);
  const saved = sessionStorage.getItem(PENDING);
  sessionStorage.removeItem(PENDING);
  history.replaceState(null, "", window.location.pathname);
  if (!saved) throw new Error("Start sign-in again.");
  const pending = JSON.parse(saved);
  if (query.get("state") !== pending.state || Date.now() - pending.startedAt > 600000) {
    throw new Error("Invalid or expired sign-in. Start again.");
  }
  if (query.has("error") || !query.get("code")) throw new Error("Sign-in was not completed.");
  const response = await fetch(new URL("token/", AUTH_BASE), {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      grant_type: "authorization_code",
      code: query.get("code"),
      code_verifier: pending.verifier,
      redirect_uri: REDIRECT_URI,
    }),
  });
  if (!response.ok) throw new Error("Code exchange failed. Start sign-in again.");
  tokens = await response.json();
  return getSession();
}

export async function getSession() {
  if (!tokens) return null;
  const response = await fetch(new URL("session/", AUTH_BASE), {
    headers: { Authorization: `Bearer ${tokens.access_token}` },
    cache: "no-store",
  });
  if (!response.ok) {
    tokens = null;
    throw new Error("Session check failed. Sign in again.");
  }
  return response.json();
}

export async function signOut() {
  const current = tokens;
  tokens = null;
  if (!current) return;
  const response = await fetch(new URL("session/", AUTH_BASE), {
    method: "DELETE",
    headers: { Authorization: `Bearer ${current.access_token}` },
  });
  if (response.status !== 204) throw new Error("Local state cleared; server logout failed.");
}
```

Crida `signIn()` des del botó d'inici de sessió. A la pàgina de callback registrada, crida `handleCallback()` una sola vegada, mostra un estat de càrrega i mostra el seu error si falla. Utilitza `getSession()` per obtenir l'usuari actual i `signOut()` per tancar la sessió. El callback elimina el seu codi de la barra d'adreces abans de fer cap sol·licitud.

Aquest exemple mínim manté els tokens a la memòria i torna a iniciar sessió després de recarregar la pàgina o quan caduca el token d'accés. Per a sessions persistents, utilitza el teu backend i cookies segures, o implementa una [rotació de refresh](https://docs.didit.me/ca/authentication/tokens-and-jwks.md) serialitzada. Mai no posis refresh tokens a les URL ni als registres. La comprovació de sessió del frontend només controla la presentació; el teu backend ha de validar la persona que fa la crida a cada sol·licitud protegida.

## Versió preliminar del SDK d'autenticació

El nucli planificat de `@didit-protocol/auth` exposa `createDiditAuth({publishableKey})`, `signIn()`, `handleRedirectCallback()`, `getSession()`, `getToken()`, `onAuthStateChange` i `signOut()`, amb `vendorData` a la identitat. Està previst que afegeixi senyals automàtics del dispositiu i un punt d'entrada al servidor amb `verifyToken()`.

La clau publicable és `pk_live_` (aplicació de producció) o `pk_test_` (aplicació de sandbox) seguida de la codificació base64url, sense farciment, de l'origen de la teva aplicació.
El SDK envia les seves crides d'API a aquest origen.
La clau és pública: identifica l'aplicació i no és un secret.

### Step-up i reautenticació a la versió preliminar

* `stepUp({ action, amount?, currency?, redirectUri? })` crida `POST step-up/` de la teva aplicació per preguntar si `action` necessita una verificació d'identitat.
  `action` és `payout`, `bank` o `contact`, i un pagament necessita `amount`.
  Quan s'aplica una de les teves regles de step-up, navega a la pàgina de verificació que retorna Didit.
* `handleStepUpCallback(url?)` s'executa a la pàgina on torna la persona.
  Llegeix `?step_up=<id>`, l'elimina de la barra d'adreces i llegeix el resultat amb `GET step-up/{id}/`.
* `reauthenticate({ method? })` torna a iniciar sessió amb la mateixa persona, a la pàgina allotjada (`method: "redirect"`, el valor per defecte) o amb una passkey (`method: "passkey"`, només al domini d'inici de sessió de Didit de la teva aplicació).
  Després de la pàgina allotjada, completa-la amb `handleRedirectCallback()`.
  Si una altra persona la completa, es rebutja amb `step_up_user_mismatch` i la sessió original es manté.

Els dos mètodes de step-up es resolen amb `{ id, status, approved, rule, method }`, on `status` és `not_required`, `pending`, `approved`, `review`, `declined` o `expired`.
`redirectUri` pren per defecte l'adreça de redirecció del client i ha de coincidir exactament amb una de les adreces de redirecció registrades de la teva aplicació: quan es requereix una verificació, Didit rebutja qualsevol altra adreça.
Abans que el teu backend actuï sobre un step-up, el torna a llegir amb `GET step-up/{id}/` i amb el token d'accés de la persona, perquè un resultat informat pel navegador es pot modificar.

Un inici de sessió sense interfície també pot respondre `protection_required` quan les regles de protecció de la teva aplicació el marquen. La persona aleshores el completa amb el codi que Didit li ha enviat per correu electrònic (`protection.verify({ code })`) o amb una passkey (`protection.passkey()`), i `methods` indica quins dels dos pot utilitzar.

No instal·lis una versió basada en conjectures ni escriguis codi basant-te en opcions de callback suposades. Abans de substituir l'exemple allotjat, confirma les exportacions del paquet publicat, l'emissor i la configuració de les claus. Els mètodes de contrasenya, codi de correu electrònic, enllaç màgic, passkey, telèfon, MFA, inici de sessió social, step-up i d'agent dependran de l'API que admeti aquella versió.

## Afegeix altres productes

El teu backend verifica el token d'accés (consulta [tokens i JWKS](https://docs.didit.me/ca/authentication/tokens-and-jwks.md)) i llegeix el seu `vendor_data`. Utilitza aquest valor com a `vendor_data` en [crear una sessió de verificació](https://docs.didit.me/ca/sessions-api/create-session.md) o en [emetre un token de transacció](https://docs.didit.me/ca/transaction-monitoring/sdk-transaction-submission.md). Un inici de sessió correcte no implica que cap dels dos productes hagi aprovat l'usuari.

Abans de desplegar, prova l'alta, l'inici de sessió dels usuaris que tornen, la cancel·lació, l'estat no coincident, el codi reutilitzat, la recuperació de contrasenya, MFA, la caducitat i el tancament de sessió a la teva aplicació de sandbox habilitada.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.