跳到正文

@xid-kit/remix

带 React SDK 重导出的 Remix loader 和 action 服务端辅助工具、cookie 会话存储和 OAuth callback 处理器。

状态

包状态为 当前包。Remix loader/action 认证辅助工具、cookie 会话集成和 OAuth callback 处理器已实现。在真实生产基础设施上的 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 token 或会话 cookie,以 networkless 方式验证,并返回 AuthResultrequireAuth 在未认证时自动抛出重定向到 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 callback 处理器

handleCallback 校验 state 参数以防 CSRF,交换授权码,并返回带 Set-CookieResponse

// 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>
  )
}

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 token 的 Remix cookie 会话存储
getAuth function 验证 JWT 或会话 token;返回 AuthResult
requireAuth function 类似 getAuth,但在未认证时抛出重定向响应
handleCallback function OAuth callback:校验 state,交换 code,设置会话 cookie
xidClient function 返回绑定到密钥的服务端 Management API 客户端
getTokenFromSession, setTokensInSession, clearTokensFromSession 函数 用于自定义会话处理的底层 token 辅助工具

重新导出

重导出所有 @xid-kit/react 客户端组件和 hook,使 root.tsx 只需一次导入即可获得 provider 和客户端组件。

PKCE 和安全

  • 公共客户端使用带 PKCE S256 的授权码。不存储客户端密钥。
  • handleCallback 校验 state 参数与会话以防 CSRF。
  • 访问令牌存储在 HttpOnly 会话 cookie 中,不会写入 localStorage
导航

输入内容以搜索...

使用方向键导航按 Enter 键选择按 Escape 键关闭