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-ts | TypeScript 实现的 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>,
);配置说明:
| 字段 | 说明 |
|---|---|
authority | Code Bird Cloud 的 Issuer 地址,库会自动调用 /.well-known/openid-configuration |
client_id | SPA 应用的 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 | 认证用户信息,包含 profile、access_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 };
}逻辑说明:
- 从
useAuth()获取当前用户的 Access Token - 在请求的
AuthorizationHeader 中携带 Bearer Token - 当 API 返回 401 时,尝试静默刷新令牌并重试
- 如果静默刷新也失败,重定向用户到登录页面
运行
bash
# 启动开发服务器
npm run dev访问 http://localhost:5173,点击 "Login" 按钮开始登录流程。
回调路由处理
react-oidc-context 的 AuthProvider 会自动处理回调路由。当用户从 Code Bird Cloud 重定向回 redirect_uri 时,库会自动完成授权码交换和令牌存储。
如果你使用 React Router,确保回调路径不会被其他路由拦截:
tsx
// If using React Router, no special route needed for /callback
// AuthProvider handles it automatically