SDK JavaScript pour navigateur

@keenauth/js est le cœur navigateur de KeenAuth. Il connecte les utilisateurs à votre application monopage, conserve leurs jetons et appelle votre API. Il n'a aucune dépendance d'exécution, et les composants React reposent sur lui. Le package n'est pas encore publié sur npm.

Se connecter avec une redirection

Le SDK est un client public OpenID Connect standard :

import { KeenAuth } from "@keenauth/js";

const auth = new KeenAuth({
  issuer: "https://acme.eu.keenauth.app", // your environment's issuer, exactly
  clientId: "app_01j9zzzzzzzzzzzzzzzzzzzz",
  redirectUri: "https://app.acme.example/callback",
  postLogoutRedirectUri: "https://app.acme.example/",
});

// On your sign-in button:
await auth.signInRedirect({ appState: "/orders" });

// On https://app.acme.example/callback:
const { appState } = await auth.handleRedirectCallback();

handleRedirectCallback n'accepte une réponse qu'une seule fois. Il échoue avec une KeenAuthError lorsque :

Une erreur renvoyée par le serveur est levée sous la forme d'une KeenAuthOAuthError contenant le code error d'OAuth.

Appeler votre API

Pour obtenir un jeton d'accès pour votre API, transmettez son identifiant dans resource (RFC 8707). Il est envoyé dans la requête d'autorisation, l'échange du code et chaque renouvellement, et le aud du jeton correspond à cet identifiant :

const auth = new KeenAuth({
  issuer: "https://acme.eu.keenauth.app",
  clientId: "app_01j9zzzzzzzzzzzzzzzzzzzz",
  redirectUri: "https://app.acme.example/callback",
  resource: "https://api.acme.example", // your API's identifier
  scope: "openid profile email offline_access messages:read",
});
const res = await auth.authorizedFetch("https://api.acme.example/v1/orders");

// Or take the token yourself; it is refreshed when it is about to expire.
const token = await auth.getAccessToken();

authorizedFetch envoie Authorization: DPoP avec une preuve récente liée au jeton. Si le serveur demande un nonce DPoP, la requête est relancée une fois avec ce nonce. Les appels simultanés partagent une seule requête de renouvellement, et chaque renouvellement remplace le jeton de rafraîchissement. Pour vérifier ces jetons dans votre API, consultez Vérifier les jetons dans votre API.

Se déconnecter

await auth.signOut();

signOut supprime les jetons et révoque le jeton de rafraîchissement. Il redirige ensuite le navigateur vers le point de terminaison de déconnexion de votre environnement, qui le renvoie vers postLogoutRedirectUri.

Où sont conservés les jetons

Connexion intégrée

Le même objet fournit également aux composants intégrés un client d'API frontale :

Ces appels utilisent les cookies de votre environnement et un en-tête CSRF. Le serveur ne les accepte que depuis l'origine de connexion de l'environnement.

Se connecter sans redirection

Sur une page située hors de l'origine de connexion de votre environnement, démarrez la transaction avec votre clientId. Le SDK la lie alors à sa clé DPoP au lieu des cookies :

let tx = await auth.transactions.create({ client_id: "app_01j9...", organization: "acme" });
tx = await auth.transactions.step("identifier", { identifier: "ada@acme.example" });
tx = await auth.transactions.step("password", { password });
if (tx.state === "completed") await auth.complete(tx); // { kind: "signed_in" }

Appels au compte depuis votre propre origine

Une fois l'utilisateur connecté et le SDK en possession d'un jeton de rafraîchissement (la portée par défaut demande offline_access), les appels me et organizations n'ont plus besoin du cookie de session de l'hôte de connexion :

Consultez Jeton d'accès à l'API frontale pour les règles côté serveur.

Changer d'organisation

organizations.switch(orgId) fait passer l'utilisateur connecté vers une autre organisation sans changer de page. Transmettez l'identifiant org_… d'une organisation renvoyée par organizations.listMine() :

const { data } = await auth.organizations.listMine();
await auth.organizations.switch(data[1].id);

Limites actuelles