ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

React 应用集成 SpacetimeAuth 实战指南:基于 react-oidc-context 的 OIDC 登录接入

React 应用集成 SpacetimeAuth 实战指南:基于 react-oidc-context 的 OIDC 登录接入 React 应用集成 SpacetimeAuth 实战指南基于 react-oidc-context 的 OIDC 登录接入【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDBSpacetimeAuth 是 SpacetimeDB 提供的托管式 OpenID ConnectOIDC身份认证服务本文以当前仓库中的 React 集成指南 为核心完整讲解如何借助react-oidc-context库在一个 React 应用中接入 SpacetimeAuth 的登录、登出、静默续期与用户信息展示。读完本文你将掌握从 SpacetimeAuth 项目创建、客户端配置到 React 端 OIDC 配置对象、调试组件、AuthProvider包裹与自动登录的完整链路并知道如何把拿到的 ID Token 交给任意 SpacetimeDB SDK 建立认证连接。:::warning 关于 Beta 状态SpacetimeAuth 目前处于 beta 阶段部分功能可能尚未提供或会在未来发生变化使用过程中可能会遇到 bug 或问题。官方欢迎将遇到的问题反馈给 SpacetimeAuth 团队以帮助改进服务。 :::一、SpacetimeAuth 与 React 集成概览根据 SpacetimeAuth 概述SpacetimeAuth 是一个专门为 SpacetimeDB 应用构建的托管 OIDC Provider用于管理应用的认证。你无需自建外部认证服务或托管服务器即可完成用户认证。由于它遵循 OIDC 协议因此可以与任何兼容 OIDC 的客户端库配合使用——react-oidc-context正是其中针对 React 生态的成熟选择它提供了一套简单的方式在 React 中处理 OIDC 认证状态。整个认证流程的终点是你的应用获得一个包含身份声明identity claims如 email、username、roles的ID Token随后可以携带该 Token 通过任意 SpacetimeDB SDK 与服务器完成认证与授权。在 React 场景下这个拿到 ID Token的动作由react-oidc-context全权托管。二、前置准备从项目创建到客户端配置1. 启用 SpacetimeAuth 并创建项目按照 创建项目指南 的步骤操作先在 Maincloud 上部署你的模块参考 Deploy to Maincloud进入已部署模块的仪表盘右上角头像 → My profile → 选择模块在左侧边栏点击 SpacetimeAuth点击 Use SpacetimeAuth 按钮启用服务项目创建后仪表盘会提供Overview项目概览与近期用户、Clients客户端列表创建项目时会自动生成一个默认客户端、Users用户管理、Identity Providers第三方身份提供商和Customization登录页主题与认证方式定制等管理标签页。这里需要理解两个容易混淆的概念Clients是依赖方Relying Party即请求 OIDC ID Token 的应用每个客户端关联唯一项目并拥有独立的 client ID 与 client secret而Users是最终登录用户拥有唯一标识和若干角色。角色如admin、user会作为声明写入签发给用户的 ID Token供模块端 reducer 做访问控制判断。2. 配置客户端Client创建项目后进入Clients标签页配置你的客户端。创建或编辑客户端时可配置配置项说明Name客户端名称例如 My Web AppRedirect URIs登录成功后 SpacetimeAuth 允许将用户重定向回的 URI 列表必须与应用中实际使用的 URI 完全一致Post Logout Redirect URIs登出后允许重定向回的 URI 列表同样必须与应用中的 URI 匹配Redirect URI 是 OAuth2 / OIDC 流程中保证安全的关键一环配置时必须保证schemehttp/https、域名、端口如有和路径完全精确匹配。例如应用托管在https://myapp.com、从https://myapp.com/login发起登录流程则可将 redirect URI 设为https://myapp.com/callback。这正是后文 React 配置对象中redirect_uri字段要与 Dashboard 里登记的 URI 一一对应的原因。:::danger 客户端密钥安全 client secret 是敏感信息绝不能出现在客户端代码或公开仓库中client ID 则不是敏感信息可以放心共享。client secret 仅在client_credentials流程中使用用于获取无用户上下文的 Token此时sub声明会被置为 client ID。 :::3. 了解 Scopes 与 Claims目前 SpacetimeAuth 的 scope 暂不可编辑限定为openid、profile、email三个已足以覆盖大多数应用场景。各 scope 提供的 ID Token 声明claims如下ScopeClaimsopenid必选sub唯一用户标识profilename、family_name、given_name、middle_name、nickname、preferred_username、picture、website、gender、birthdate、zoneinfo、locale、updated_atemailemail、email_verified在发起认证流程时可以请求全部或其中一部分 scope。后文的 OIDC 配置对象即采用openid profile email组合这也是 配置项目指南 建议的标准用法。4. 安装 react-oidc-context确保已有一个可用的 React 应用Create React App 或其他 React 框架均可然后安装依赖npm install react-oidc-context5. 推荐先用 OIDC Debugger 验证配置在写代码之前建议先用 OIDC Debugger它能模拟浏览器中的 OAuth2 / OIDC Authorization Code 流程帮你确认 redirect URI 与 client ID 是否正确、并提前检查 ID Token 中的 claims。测试所需的端点为Authorization Endpointhttps://auth.spacetimedb.com/oidc/authToken Endpointhttps://auth.spacetimedb.com/oidc/token在 OIDC Debugger 中填写Authorize URI 指向/oidc/authClient ID 填你的客户端 IDScope 填openid profile email或子集勾选Use PKCEToken URI 指向/oidc/token同时把https://oidcdebugger.com/debug加入 Dashboard 中该客户端的允许 redirect URI。注意此工具运行在浏览器中无需填写 client secret。成功后可解码 ID Token 看到如下形式的 claims{ sub: user_ergqg1q5eg15fdd54, project_id: project_xyz123, email: userexample.com, email_verified: true, preferred_username: exampleuser, first_name: Example, last_name: User, name: Example User }三、配置 react-oidc-contextOIDC 配置对象详解集成第一步是创建一个包含 SpacetimeAuth 项目信息的 OIDC 配置对象。请将YOUR_CLIENT_ID替换为 SpacetimeAuth Dashboard 中的真实客户端 IDconst oidcConfig { authority: https://auth.spacetimedb.com/oidc, client_id: YOUR_CLIENT_ID, redirect_uri: ${window.location.origin}/callback, // Where the user is redirected after login post_logout_redirect_uri: window.location.origin, // Where the user is redirected after logout scope: openid profile email, response_type: code, automaticSilentRenew: true, };各字段含义与对应关系字段值说明authorityhttps://auth.spacetimedb.com/oidcOIDC Provider 的权威地址react-oidc-context会据此发现元数据与上文 Authorization / Token Endpoint 同源client_id你的 SpacetimeAuth 客户端 ID对应 Dashboard 中创建的 Clientredirect_uri${window.location.origin}/callback登录后重定向回的应用地址必须已登记在 Dashboard 的 Redirect URIs 中且 scheme/域名/端口/路径完全一致post_logout_redirect_uriwindow.location.origin登出后重定向回的地址同样需在 Dashboard 的 Post Logout Redirect URIs 中登记scopeopenid profile email按需请求的 scope见上文 Claims 表格可只取子集response_typecode使用 Authorization Code 流程配合 PKCE代码不会直接暴露 TokenautomaticSilentRenewtrue启用静默续期access token 即将过期时在后台自动刷新避免用户被强制重新登录从 配置项目指南 可知redirect URI 的匹配是精确的包括 http/https、域名、端口、路径因此在本地开发时例如http://localhost:3000/callback和线上部署时可能需要为同一客户端登记多个 redirect URI或为不同环境维护独立客户端。四、创建调试组件OidcDebug该组件将各类认证事件和状态变化打印到控制台便于在开发阶段排查问题。它会通过useAuth()拿到auth.events订阅react-oidc-context暴露的事件总线并在组件卸载时清理监听器export function OidcDebug() { const auth useAuth(); useEffect(() { const ev auth.events; const onUserLoaded (u: any) console.log([OIDC] userLoaded, u?.profile?.sub, u); const onUserUnloaded () console.log([OIDC] userUnloaded); const onAccessTokenExpiring () console.log([OIDC] accessTokenExpiring); const onAccessTokenExpired () console.log([OIDC] accessTokenExpired); const onSilentRenewError (e: any) console.warn([OIDC] silentRenewError, e); const onUserSignedOut () console.log([OIDC] userSignedOut); ev.addUserLoaded(onUserLoaded); ev.addUserUnloaded(onUserUnloaded); ev.addAccessTokenExpiring(onAccessTokenExpiring); ev.addAccessTokenExpired(onAccessTokenExpired); ev.addSilentRenewError(onSilentRenewError); ev.addUserSignedOut(onUserSignedOut); return () { ev.removeUserLoaded(onUserLoaded); ev.removeUserUnloaded(onUserUnloaded); ev.removeAccessTokenExpiring(onAccessTokenExpiring); ev.removeAccessTokenExpired(onAccessTokenExpired); ev.removeSilentRenewError(onSilentRenewError); ev.removeUserSignedOut(onUserSignedOut); }; }, [auth.events]); useEffect(() { console.log([OIDC] state, { isLoading: auth.isLoading, isAuthenticated: auth.isAuthenticated, error: auth.error?.message, activeNavigator: auth.activeNavigator, user: !!auth.user, }); }, [ auth.isLoading, auth.isAuthenticated, auth.error, auth.activeNavigator, auth.user, ]); return null; }各事件的调试价值userLoaded/userUnloaded用户会话加载与清除可在userLoaded回调中确认sub唯一用户标识并与上文 OIDC Debugger 解码出的sub对照accessTokenExpiring/accessTokenExpired配合automaticSilentRenew: true使用若静默续期失败会看到相应日志silentRenewError静默续期出错时打印警告是排查用户被莫名登出问题的第一入口userSignedOut用户登出信号第二个useEffect则持续输出isLoading、isAuthenticated、error、activeNavigator、user等状态快照。五、用 AuthProvider 包裹应用在应用入口处用AuthProvider包裹整棵组件树为所有子组件提供认证上下文。这里把oidcConfig展开传入并配置onSigninCallbackimport React from react; import ReactDOM from react-dom/client; import { AuthProvider, useAuth } from react-oidc-context; import App from ./App; import { OidcDebug } from ./OidcDebug; const oidcConfig {...}; function onSigninCallback() { window.history.replaceState({}, document.title, window.location.pathname); } const root ReactDOM.createRoot(document.getElementById(root) as HTMLElement); root.render( AuthProvider {...oidcConfig} onSigninCallback{onSigninCallback} OidcDebug / App / /AuthProvider );onSigninCallback的作用是登录成功重定向回应用后浏览器地址栏仍残留?code...state...之类的查询参数。该回调在react-oidc-context处理完授权响应后触发通过history.replaceState将 URL 清理为干净的路径避免回调参数暴露在地址栏中也避免刷新页面时被重复处理。六、在应用组件中实现认证逻辑在主组件如App.tsx中使用useAutoSignin钩子在用户未认证时自动发起登录跳转import React from react; import { useAuth, useAutoSignin } from react-oidc-context; import ./App.css; function App() { const auth useAuth(); useAutoSignin(); if (auth.isLoading) { return divLoading.../div; } if (auth.error) { return divError: {auth.error.message}/div; } if (!auth.isAuthenticated) { return divRedirecting to login.../div; } return ( div classNameApp header classNameApp-header Welcome, {auth.user?.profile.name} (id: {auth.user?.profile.sub})! button onClick{() auth.signoutRedirect()}Sign Out/button /header /div ); }这段逻辑的执行顺序正是 OIDC 状态机的标准处理路径useAutoSignin()负责未认证则自动跳转登录页——当用户首次访问且未登录时react-oidc-context会引导用户跳转到authority对应的 SpacetimeAuth 登录页auth.isLoading为true时展示加载态静默续期期间也会进入该状态此时不应渲染业务界面auth.error存在时展示错误信息例如 redirect URI 不匹配、code 交换失败等都会在此暴露未认证时展示正在跳转登录提示认证成功后从auth.user?.profile读取用户信息——profile.name来自profilescope 的name声明profile.sub即用户唯一标识点击Sign Out按钮调用auth.signoutRedirect()登出后会重定向到post_logout_redirect_uri。完成以上四步后SpacetimeAuth 已成功接入你的 React 应用用户访问应用时会被重定向到 SpacetimeAuth 登录页完成认证。七、登录之后把 ID Token 交给 SpacetimeDB SDK拿到认证身份只是第一步。根据 连接与认证文档客户端连接 SpacetimeDB 时可通过withToken系列方法携带来自 SpacetimeAuth 的 Tokenauth.user?.id_token服务器会在连接时校验 Token 并提取身份声明。各语言 SDK 的用法// TypeScript const conn DbConnection.builder() .withUri(https://maincloud.spacetimedb.com) .withDatabaseName(my_database) .withToken(your_auth_token_here) .build();// C# var conn DbConnection.Builder() .WithUri(https://maincloud.spacetimedb.com) .WithDatabaseName(my_database) .WithToken(your_auth_token_here) .Build();// Rust let conn DbConnection::builder() .with_uri(https://maincloud.spacetimedb.com) .with_database_name(my_database) .with_token(your_auth_token_here) .build();// Unreal UDbConnection* Conn UDbConnection::Builder() -WithUri(TEXT(https://maincloud.spacetimedb.com)) -WithDatabaseName(TEXT(my_database)) -WithToken(TEXT(your_auth_token_here)) -Build();同时注意 认证概述 中关于 Token 持久化的提醒如果客户端未携带 Token 连接SpacetimeDB 会创建一个新身份并返回服务器签发的长寿命 Token应将这个 Token 持久化以便重连时保持同一身份而重连时通过 WebSocket 握手换取的短寿命 WebSocket Token不应覆盖已保存的长寿命 Token——这一点在浏览器类传输环境如 Unity WebGL中尤其重要。在 React 应用中react-oidc-context的automaticSilentRenew会维护访问令牌的有效期你可以把auth.user?.id_token接入上述 SDK 连接逻辑实现登录 → 携带 Token 连接 SpacetimeDB → 模块端按角色授权的完整闭环。八、常见问题与排查建议结合 测试指南 与 配置指南集成过程中最常见的问题集中在以下几类现象可能原因排查方向登录后跳转回应用但报 redirect 错误Dashboard 中登记的 Redirect URI 与应用内redirect_uri不完全一致核对 scheme、域名、端口、路径本地与线上需分别登记auth.error出现错误信息code 交换失败、PKCE 参数不一致或客户端配置错误先用 OIDC Debugger 验证 Authorization / Token 端点与 client ID浏览器控制台查看OidcDebug的silentRenewError日志令牌莫名过期、用户被登出静默续期失败检查automaticSilentRenew是否开启、silentRenewError事件输出拿到 Token 后连接被拒Token 未通过模块端校验或身份声明缺失确认请求的 scope 覆盖所需 claims见 Claims 表格参考模块端 reducer 对ctx.sender_auth()的处理SpacetimeAuth 当前处于 beta 阶段配置项如 scope 的可编辑性与端点行为未来可能调整本文所述以当前仓库文档与示例为准。如需进一步了解用户、角色与授权管理可继续阅读 SpacetimeAuth 概述 与 项目配置指南。【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进