콘텐츠로 건너뛰기

@xid-kit/remix

React SDK 재내보내기가 포함된 Remix loader/action 서버 헬퍼, cookie 세션 저장소, OAuth 콜백 핸들러.

Markdown으로 보기

상태

패키지 상태: 현재 패키지. Remix loader/action 인증 헬퍼, cookie 세션 통합, OAuth 콜백 핸들러가 구현되었습니다. 프로덕션 인프라에서의 실제 IdP 왕복 테스트는 아직 수동 검증 대기 중입니다.

세션 저장소 설정

// app/sessions.server.ts
import { createXidSessionStorage } from '@xid-kit/remix'

export const sessionStorage = createXidSessionStorage({
  secret: process.env.SESSION_SECRET!, // required: cookie signing secret
  // cookieName: '__xid_session', maxAge: 2592000, secure: true
})

loader에서 인증 읽기

getAuth는 bearer 토큰 또는 세션 cookie를 추출하여 네트워크 호출 없이 검증한 후 AuthResult를 반환합니다. requireAuth는 미인증 시 자동으로 redirectPath로 302 리디렉션을 발생시킵니다.

import { getAuth, requireAuth } from '@xid-kit/remix'
import { json, redirect } from '@remix-run/node'
import type { LoaderFunctionArgs } from '@remix-run/node'
import { sessionStorage } from '~/sessions.server'

// Optional check
export async function loader({ request }: LoaderFunctionArgs) {
  const auth = await getAuth(request, {
    jwtKey: process.env.XID_JWT_KEY!,
    sessionStorage,
  })
  if (!auth.userId) return redirect('/login')
  return json({ userId: auth.userId, orgId: auth.orgId })
}

// Guard: throws redirect automatically when unauthenticated
export async function protectedLoader({ request }: LoaderFunctionArgs) {
  const auth = await requireAuth(
    request,
    { jwtKey: process.env.XID_JWT_KEY!, sessionStorage },
    { redirectPath: '/login' },
  )
  return json({ userId: auth.userId })
}

OAuth 콜백 핸들러

handleCallback은 CSRF를 방지하기 위해 state 파라미터를 검증하고, 인증 코드를 교환한 후 Set-Cookie가 포함된 Response를 반환합니다.

// app/routes/auth.callback.ts
import { handleCallback } from '@xid-kit/remix'
import type { ActionFunctionArgs } from '@remix-run/node'
import { sessionStorage } from '~/sessions.server'

export async function action({ request }: ActionFunctionArgs) {
  const result = await handleCallback(request, {
    clientId: process.env.XID_CLIENT_ID!,
    redirectUri: process.env.XID_REDIRECT_URI!,
    sessionStorage,
    defaultReturnTo: '/dashboard',
  })

  if (!result.ok) throw new Response(result.error, { status: 400 })
  return result.response // 302 redirect + Set-Cookie
}

클라이언트 provider(root.tsx)

import { XidProvider } from '@xid-kit/remix' // re-export from @xid-kit/react
import { useLoaderData, Outlet } from '@remix-run/react'

export default function App() {
  const { auth } = useLoaderData<typeof loader>()
  return (
    <XidProvider
      publishableKey={window.ENV.XID_PUBLISHABLE_KEY}
      initialState={auth.userId ? { userId: auth.userId } : undefined}
    >
      <Outlet />
    </XidProvider>
  )
}

관리 API 클라이언트

import { xidClient } from '@xid-kit/remix'

const client = xidClient({ secretKey: process.env.XID_SECRET_KEY! })

export async function loader() {
  const result = await client.getUser('user_abc')
  if (!result.ok) throw new Response(result.error.message, { status: result.error.status })
  return json(result.value)
}

내보내진 API

내보내기 종류 목적
createXidSessionStorage function XID 토큰을 위한 Remix cookie 세션 저장소
getAuth function JWT 또는 세션 토큰을 검증합니다; AuthResult를 반환합니다
requireAuth function getAuth와 유사하지만 미인증 시 리디렉션 응답을 발생시킵니다
handleCallback function OAuth 콜백: state를 검증하고 코드를 교환하며 세션 cookie를 설정합니다
xidClient function secret key에 바인딩된 서버 측 관리 API 클라이언트를 반환합니다
getTokenFromSession, setTokensInSession, clearTokensFromSession 함수 사용자 정의 세션 처리를 위한 저수준 토큰 헬퍼

재내보내기

root.tsx가 provider와 클라이언트 컴포넌트 모두에 대해 하나의 가져오기만 필요하도록 모든 @xid-kit/react 클라이언트 컴포넌트와 hook을 재내보냅니다.

PKCE 및 보안

  • 공개 클라이언트는 PKCE S256을 사용한 Authorization Code를 사용합니다. client secret은 저장되지 않습니다.
  • handleCallback은 CSRF를 방지하기 위해 세션에 대한 state 파라미터를 검증합니다.
  • 액세스 토큰은 HttpOnly 세션 cookie에 저장되며 localStorage에는 기록되지 않습니다.
탐색

입력하여 검색...

화살표 키로 이동Enter 키로 선택Escape 키로 닫기