コンテンツへ移動

@xid-kit/remix

Remix ローダーとアクションサーバーヘルパー、Cookie セッションストレージ、React SDK の再エクスポートを含む OAuth コールバックハンドラー。

Markdown で表示

状態

パッケージステータス:現行パッケージ。Remix ローダー/アクション認証ヘルパー、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
})

ローダーでの認証読み取り

getAuth はベアラートークンまたはセッション 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
}

クライアントプロバイダー(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>
  )
}

Management 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 シークレットキーに紐付けられたサーバーサイド Management API クライアントを返します
getTokenFromSession, setTokensInSession, clearTokensFromSession 関数 カスタムセッション処理用の低レベルトークンヘルパー

再エクスポート

すべての @xid-kit/react クライアントコンポーネントとフックを再エクスポートします。root.tsx はプロバイダーとクライアントコンポーネントの両方に 1 つのインポートのみで済みます。

PKCE とセキュリティ

  • パブリッククライアントは PKCE S256 付き認可コードを使用します。クライアントシークレットは保存されません。
  • handleCallback は CSRF を防ぐためにセッションに対して state パラメーターを検証します。
  • アクセストークンは HttpOnly セッション Cookie に保存されます。localStorage には書き込まれません。
ナビゲーション

入力して検索...

矢印キーで移動Enter キーで選択Escape キーで閉じる