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은 응답을 한 번만 허용합니다. 다음의 경우 KeenAuthError와 함께 실패합니다:

서버가 되돌려 보낸 오류는 OAuth error 코드를 담은 KeenAuthOAuthError로 발생합니다.

API 호출하기

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 nonce를 요구하면, 그 nonce로 한 번 재시도합니다. 동시 호출은 하나의 갱신 요청을 공유하며, 모든 갱신은 갱신 토큰을 교체합니다. API에서 이 토큰을 검증하는 방법은 API에서 토큰 검증하기를 참조하십시오.

로그아웃

await auth.signOut();

signOut은 토큰을 삭제하고 갱신 토큰을 취소합니다. 그런 다음 브라우저를 환경의 로그아웃 엔드포인트로 보내며, 이 엔드포인트는 브라우저를 postLogoutRedirectUri로 되돌립니다.

토큰 보관 위치

내장 로그인

같은 객체는 내장 컴포넌트에 프런트 API 클라이언트도 제공합니다:

이 호출은 환경의 쿠키와 CSRF 헤더를 사용합니다. 서버는 환경 자체의 로그인 출처에서 온 요청만 허용합니다.

리디렉션 없이 로그인

로그인 출처 밖의 페이지에서는 clientId로 트랜잭션을 시작합니다. 그러면 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 호출은 더 이상 로그인 호스트의 세션 쿠키를 필요로 하지 않습니다:

서버 규칙은 프런트 API 액세스 토큰을 참조하십시오.

조직 전환

organizations.switch(orgId)는 페이지 이동 없이 로그인한 사용자를 다른 조직으로 옮깁니다. organizations.listMine()에서 얻은 조직의 org_… ID를 전달하십시오:

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

현재 제한 사항