Skip to content

React SPA 集成教程

本教程介绍如何使用 React + oidc-client-ts + react-oidc-context 通过 Authorization Code + PKCE 流程集成 Code Bird Cloud 进行用户认证。

前置条件

  • Node.js 18 或更高版本
  • 一个 React 项目(使用 Vite、Create React App 或其他脚手架)
  • 已在 Code Bird Cloud 管理后台创建 SPA 类型的应用,并获取 Client ID
  • 已配置 Redirect URI 为 http://localhost:5173/callback
  • 已配置 Post Logout Redirect URI 为 http://localhost:5173

SPA 类型的应用不需要 Client Secret,PKCE 机制替代了 Secret 的作用。

安装依赖

bash
npm install oidc-client-ts react-oidc-context
依赖包说明
oidc-client-tsTypeScript 实现的 OIDC 客户端库,内置 PKCE 支持
react-oidc-context基于 oidc-client-ts 的 React 封装,提供 Hook 和 Context

OIDC Provider 配置

在应用入口文件中配置 AuthProvider

tsx
// src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { AuthProvider } from 'react-oidc-context';
import App from './App';

const oidcConfig = {
  authority: 'https://your-domain.com',
  client_id: 'YOUR_CLIENT_ID',
  redirect_uri: 'http://localhost:5173/callback',
  post_logout_redirect_uri: 'http://localhost:5173',
  scope: 'openid profile email offline_access',
  // PKCE is enabled by default in oidc-client-ts
};

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <AuthProvider {...oidcConfig}>
      <App />
    </AuthProvider>
  </React.StrictMode>,
);

配置说明:

字段说明
authorityCode Bird Cloud 的 Issuer 地址,库会自动调用 /.well-known/openid-configuration
client_idSPA 应用的 Client ID
redirect_uri授权成功后的回调地址
post_logout_redirect_uri登出后的跳转地址
scope请求的权限范围,包含 offline_access 以获取 Refresh Token

oidc-client-ts 默认启用 PKCE,无需手动配置。

主应用组件

tsx
// src/App.tsx
import { useAuth } from 'react-oidc-context';

function App() {
  const auth = useAuth();

  if (auth.isLoading) {
    return <div>Loading...</div>;
  }

  if (auth.error) {
    return <div>Authentication error: {auth.error.message}</div>;
  }

  if (auth.isAuthenticated) {
    return (
      <div>
        <h1>Welcome, {auth.user?.profile.name}</h1>
        <p>Email: {auth.user?.profile.email}</p>
        <button onClick={() => auth.removeUser()}>Logout</button>
      </div>
    );
  }

  return (
    <div>
      <h1>Code Bird Cloud OIDC Demo</h1>
      <button onClick={() => auth.signinRedirect()}>Login</button>
    </div>
  );
}

export default App;

useAuth() Hook 提供的状态和方法:

属性/方法说明
auth.isLoading认证状态加载中
auth.isAuthenticated用户是否已认证
auth.user认证用户信息,包含 profileaccess_token
auth.error认证错误信息
auth.signinRedirect()发起登录重定向
auth.signinSilent()静默刷新令牌
auth.removeUser()登出并清除本地状态

使用 Access Token 调用 API

创建一个自定义 Hook,封装带认证的 API 调用逻辑:

tsx
// src/hooks/useApi.ts
import { useAuth } from 'react-oidc-context';
import { useCallback } from 'react';

export function useApi() {
  const auth = useAuth();

  const fetchWithAuth = useCallback(
    async (url: string, options: RequestInit = {}) => {
      if (!auth.user?.access_token) {
        throw new Error('Not authenticated');
      }

      const response = await fetch(url, {
        ...options,
        headers: {
          ...options.headers,
          Authorization: `Bearer ${auth.user.access_token}`,
        },
      });

      if (response.status === 401) {
        try {
          await auth.signinSilent();
          return fetch(url, {
            ...options,
            headers: {
              ...options.headers,
              Authorization: `Bearer ${auth.user.access_token}`,
            },
          });
        } catch {
          auth.signinRedirect();
          throw new Error('Session expired');
        }
      }

      return response;
    },
    [auth],
  );

  return { fetchWithAuth };
}

逻辑说明:

  1. useAuth() 获取当前用户的 Access Token
  2. 在请求的 Authorization Header 中携带 Bearer Token
  3. 当 API 返回 401 时,尝试静默刷新令牌并重试
  4. 如果静默刷新也失败,重定向用户到登录页面

运行

bash
# 启动开发服务器
npm run dev

访问 http://localhost:5173,点击 "Login" 按钮开始登录流程。

回调路由处理

react-oidc-contextAuthProvider 会自动处理回调路由。当用户从 Code Bird Cloud 重定向回 redirect_uri 时,库会自动完成授权码交换和令牌存储。

如果你使用 React Router,确保回调路径不会被其他路由拦截:

tsx
// If using React Router, no special route needed for /callback
// AuthProvider handles it automatically

相关文档

Released under the MIT License.