JavaScript ブラウザ SDK

@keenauth/js は KeenAuth のブラウザ向けコアです。シングルページアプリにユーザーをサインインさせ、トークンを保持して API を呼び出します。実行時の依存関係はなく、React コンポーネントはこのパッケージの上に構築されています。このパッケージはまだ npm に公開されていません。

リダイレクトによるサインイン

この SDK は標準的な OpenID Connect パブリッククライアントです。

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 は応答を 1 回だけ受け付けます。次の場合には KeenAuthError で失敗します。

サーバーから返されたエラーは、OAuth の error コードを保持する KeenAuthOAuthError として送出されます。

API の呼び出し

API 用のアクセストークンを取得するには、その識別子を resource (RFC 8707) として渡します。これは認可リクエスト、コードとの交換、およびすべてのリフレッシュで送信され、トークンの aud はその識別子になります。

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 は、トークンに紐づいた新しい証明を付けて Authorization: DPoP を送信します。サーバーが DPoP のノンスを要求した場合、そのノンスを付けて 1 回だけ再試行します。並行する呼び出しは 1 回のリフレッシュリクエストを共有し、リフレッシュのたびにリフレッシュトークンはローテーションされます。API でこれらのトークンを検証する方法は、API でのトークン検証を参照してください。

サインアウト

await auth.signOut();

signOut はトークンを破棄し、リフレッシュトークンを取り消します。その後、ブラウザを環境のログアウトエンドポイントへ遷移させ、postLogoutRedirectUri に戻します。

トークンの保管場所

埋め込みサインイン

同じオブジェクトから、埋め込みコンポーネント向けのフロント API クライアントも利用できます。

これらの呼び出しは、環境の Cookie と CSRF ヘッダーを使用します。サーバーは、環境自身のログインオリジンからの呼び出しのみを受け付けます。

リダイレクトなしのサインイン

ログインオリジン以外のページでは、clientId を指定してトランザクションを開始します。すると SDK は、Cookie の代わりにそのトランザクションを SDK の DPoP 鍵に紐づけます。

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" }

自身のオリジンからのアカウント呼び出し

ユーザーがサインインし、SDK がリフレッシュトークンを保持している場合 (既定のスコープは offline_access を要求します)、me と organizations の呼び出しはサインインホストのセッション Cookie を必要としなくなります。

サーバー側の規則については、フロント API アクセストークンを参照してください。

組織の切り替え

organizations.switch(orgId) は、ページを遷移させずにサインイン中のユーザーを別の組織へ移します。organizations.listMine() から取得した組織の org_… ID を渡してください。

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

現在の制限