Authentication
OAuth 2.0 の authorization code grant と PKCE に似た流れでセッショントークンが発行されます。
Get authorization code
まずユーザーを /login にリダイレクトします。このとき code_verifier と code_challenge が必要です。code_verifier はランダムに生成された文字列で、code_challenge はそれを ASCII エンコードし、SHA-256 でハッシュ化したものです。code_verifier はデバイスまたはブラウザーに保存してください。
https://gdsc-chuo-membership-backend.vercel.app/login?code_challenge=[CODE_CHALLENGE]
import { sha1 } from "@oslojs/crypto/sha1";
import { base64url } from "@oslojs/encoding";
const codeVerifier = generateCodeVerifier();
localStorage.setItem("code_verifier", codeVerifier);
const codeChallenge = generateCodeChallenge(codeVerifier);
const url = new URL("https://gdsc-chuo-membership-backend.vercel.app/login");
url.searchParams.set("code_challenge", codeChallenge);
window.location.href = url.toString();
function generateCodeVerifier(): string {
const randomBytes = new Uint8Array(32);
crypto.getRandomValues(randomBytes);
const codeVerifier = base64url.encodeNoPadding(randomBytes);
return codeVerifier;
}
function generateCodeChallenge(codeVerifier: string): string {
const bytes = new TextEncoder().encode(codeVerifier);
const codeChallenge = base64url.encodeNoPadding(sha256(bytes));
return codeChallenge;
}
Exchange authorization code for session token
/login/callback にユーザーがリダイレクトされます。
/login/callback?login_id=[LOGIN_ID]
login_id が含まれているので、それと保存した code_verifier を /session に POST するとセッショントークンを得られます。
const searchParams = new URLSearchParams(window.location.search);
const loginId = searchParams.get("login_id");
const codeVerifier = localStorage.get("code_verifier");
const response = await fetch("https://gdsc-chuo-membership-backend.vercel.app/session", {
method: "POST",
body: JSON.stringify({
login_id: loginId,
code_verifier: codeVerifier,
}),
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
});
if (response.ok) {
const result = await response.json();
const sessionToken = result.session;
localStorage.set("session", sessionToken);
}
Make authenticated requests
セッショントークンは Authorization ヘッダーで送ってください。
Authorization: Session [SESSION_TOKEN]
また、セッションの有効期限(UNIX 秒)が X-Session-Expires-At ヘッダーとしてすべてのレスポンスに含まれます。
Sign out
/session に DELETE リクエストを送ることでログアウトできます。
await fetch("https://gdsc-chuo-membership-backend.vercel.app/session", {
method: "DELETE",
headers: {
Authorization: `Session ${sessionToken}`,
},
});
CORS
frontend.com からのブラウザーリクエストのみが許可されています。