import { getChzzkOAuthConfig } from '@/lib/auth/mode'; const OPENAPI = 'https://openapi.chzzk.naver.com'; export function buildChzzkLoginUrl(state: string) { const { clientId, redirectUri } = getChzzkOAuthConfig(); const url = new URL('https://chzzk.naver.com/account-interlock'); url.searchParams.set('clientId', clientId); url.searchParams.set('redirectUri', redirectUri); url.searchParams.set('state', state); return url.toString(); } export async function exchangeAuthorizationCode(code: string, state: string) { const { clientId, clientSecret } = getChzzkOAuthConfig(); const res = await fetch(`${OPENAPI}/auth/v1/token`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ grantType: 'authorization_code', clientId, clientSecret, code, state, }), cache: 'no-store', }); const json = (await res.json().catch(() => ({}))) as { content?: { accessToken?: string; refreshToken?: string; tokenType?: string; expiresIn?: string | number; }; code?: number; }; if (!res.ok || !json.content?.accessToken) { // 외부 API 원문은 계정 정보 등이 섞일 수 있으므로 전달·기록하지 않는다. throw new Error(`치지직 인증 처리 실패 (${res.status})`); } return { accessToken: json.content.accessToken, refreshToken: json.content.refreshToken ?? null, }; } export async function fetchAuthedUser(accessToken: string) { const res = await fetch(`${OPENAPI}/open/v1/users/me`, { headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, cache: 'no-store', }); const json = (await res.json().catch(() => ({}))) as { content?: { channelId?: string; channelName?: string }; }; if (!res.ok || !json.content?.channelId) { throw new Error(`치지직 사용자 확인 실패 (${res.status})`); } return { channelId: json.content.channelId.toLowerCase(), channelName: json.content.channelName ?? null, }; } /** 확인 후 치지직 토큰 폐기 (저장하지 않음) */ export async function revokeToken( token: string, tokenTypeHint: 'access_token' | 'refresh_token' = 'access_token', ) { const { clientId, clientSecret } = getChzzkOAuthConfig(); try { await fetch(`${OPENAPI}/auth/v1/token/revoke`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientId, clientSecret, token, tokenTypeHint, }), cache: 'no-store', }); } catch { // 폐기는 best-effort } }