토큰 검증·갱신

access_token 검증, refresh_token 갱신, 만료 처리에 대한 가이드.

토큰 종류

토큰TTL형식갱신
access_token60분JWT (ES256 서명)refresh_token으로 재발급
refresh_token30일opaque (v1.<random>)사용 시 회전 (rotation)

access_token 검증 방법 (3가지 중 선택)

1. JWKS 서명 검증 (권장 — server-side)

가장 빠르고 표준적입니다. JWKS endpoint에서 공개키를 가져와 ES256 서명을 검증합니다.

GEThttps://oefybpntdguqyjrhurng.supabase.co/auth/v1/.well-known/jwks.json
인증
인증 불필요
your-app/lib/verify-jwt.ts
import { jwtVerify, createRemoteJWKSet } from "jose";
 
const JWKS = createRemoteJWKSet(
  new URL("https://oefybpntdguqyjrhurng.supabase.co/auth/v1/.well-known/jwks.json"),
);
 
export async function verify(token: string) {
  const { payload } = await jwtVerify(token, JWKS, {
    algorithms: ["ES256"],
  });
  return payload as {
    sub: string;     // user_id
    email?: string;
    exp: number;
    iat: number;
  };
}

2. /auth/verify 엔드포인트 (간단하지만 latency 추가)

JWKS 통합이 부담스러우면 CP-Auth에 위임할 수 있습니다.

POSThttps://auth.cp-platform.com/auth/verify
인증
인증 불필요
Rate Limit
600 / min
curl -X POST https://auth.cp-platform.com/auth/verify \
  -H "Content-Type: application/json" \
  -d '{"access_token": "eyJhbGc..."}'
200 응답
{
  "valid": true,
  "user_id": "uuid",
  "email": "user@example.com",
  "exp": 1741200000
}

3. payload만 디코딩 (검증 없음 — 절대 금지)

JSON.parse(atob(token.split('.')[1])) 만으로는 서명 검증이 안 됩니다. 디버깅 외에는 사용하지 마세요.

refresh_token으로 갱신

access_token이 만료(또는 곧 만료)되면 refresh_token으로 새 access_token + 새 refresh_token을 받습니다.

POSThttps://auth.cp-platform.com/auth/refresh
인증
인증 불필요
Rate Limit
300 / min
your-app/api/auth/refresh.ts
export async function POST(req: Request) {
  const cookies = req.headers.get("cookie") ?? "";
  const rt = cookies.match(/refresh_token=([^;]+)/)?.[1];
  if (!rt) return new Response(null, { status: 401 });
 
  const res = await fetch("https://auth.cp-platform.com/auth/refresh", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ refresh_token: rt }),
  });
 
  if (!res.ok) return new Response(null, { status: 401 });
  const tokens = await res.json();
 
  const response = Response.json({ ok: true });
  response.headers.append(
    "Set-Cookie",
    `access_token=${tokens.access_token}; HttpOnly; Secure; SameSite=Lax; Max-Age=3600; Path=/`,
  );
  response.headers.append(
    "Set-Cookie",
    `refresh_token=${tokens.refresh_token}; HttpOnly; Secure; SameSite=Lax; Max-Age=2592000; Path=/`,
  );
  return response;
}

로그아웃 (블랙리스트)

토큰을 즉시 무효화하려면 blacklist에 추가합니다. TTL은 24시간.

POSThttps://auth.cp-platform.com/auth/logout
인증
사용자 토큰
Rate Limit
300 / min
curl -X POST https://auth.cp-platform.com/auth/logout \
  -H "Authorization: Bearer <access_token>"

응답 후 자기 도메인의 access_token / refresh_token 쿠키도 함께 삭제하세요.

사용자 정보 조회

검증된 토큰으로 user 메타데이터를 조회합니다.

GEThttps://auth.cp-platform.com/auth/me
인증
사용자 토큰
Rate Limit
3000 / min
curl https://auth.cp-platform.com/auth/me \
  -H "Authorization: Bearer <access_token>"
응답
{
  "user_id": "uuid",
  "email": "user@example.com",
  "name": "홍길동",
  "is_admin": false
}