Backstage 接入 OneLogin OIDC 认证提供者:从应用创建到登录解析器的完整实践指南
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
OneLogin 是常见的身份提供者(IdP),支持 OpenID Connect(OIDC)协议。Backstage 的@backstage/core-plugin-api内置了 OneLogin 认证提供者,可让用户通过 OneLogin 账号完成 OpenID Connect 登录。本文以仓库文档 docs/auth/onelogin/provider.md 为骨架,结合plugins/auth-backend-module-onelogin-provider的源码与测试,完整讲解在 OneLogin 后台创建 OIDC 应用、在app-config.yaml中配置提供者、注册后端模块、配置前端登录页,以及使用内置 sign-in 解析器把 OneLogin 用户身份映射到 Backstage Catalog 用户实体的全过程。读完本文,你将能在自己的 Backstage 实例中端到端落地 OneLogin 单点登录。
OneLogin 提供者概览
OneLogin 提供者是 Backstage 内置认证提供者之一,官方文档将它与 Auth0、GitHub、GitLab、Okta 等一并列入核心提供者清单(见 docs/auth/index.md)。它基于 OIDC(OpenID Connect)协议工作:前端跳转到 OneLogin 授权端点,用户完成登录后由 OneLogin 返回授权码,后端使用授权码换取访问令牌与用户资料,最终通过 sign-in 解析器把身份映射为 Backstage Catalog 中的 User 实体。
从仓库实现看,该提供者由一个独立的 auth 后端模块承载,包名为@backstage/plugin-auth-backend-module-onelogin-provider(package.json),其底层依赖passport-onelogin-oauth策略完成 OAuth 流程(authenticator.ts)。
第一步:在 OneLogin 后台创建 OIDC 应用
要启用 OneLogin 认证,首先需要在 OneLogin Admin Portal 中创建一个 OIDC 类型的 Application,步骤如下:
- 进入 OneLogin 管理后台,选择Applications;
- 点击Add App,选择OpenID Connect应用类型;
- 在Display Name中填写
Backstage(或你自己的应用名);
- 在Display Name中填写
- 点击Save保存;
- 进入该应用的Configuration标签页,设置:
Login Url:http://localhost:3000(对应 Backstage 前端地址);Redirect URIs:http://localhost:7007/api/auth/onelogin/handler/frame(对应 auth 后端回调地址);
- 点击Save;
- 进入SSO标签页,设置:
Token Endpoint>Authentication Method:POST;
- 点击Save。
其中Redirect URIs是 OIDC 流程中 OneLogin 回跳的地址,路径中的/handler/frame表示使用 iframe 弹窗式登录流程。Token Endpoint的认证方式必须设为POST,否则令牌交换可能失败。
第二步:在 app-config.yaml 中配置提供者
OneLogin 提供者的配置需要添加到app-config.yaml根级auth配置下,格式如下(来自原文档并保持完整):
auth: environment: development providers: onelogin: development: clientId: ${AUTH_ONELOGIN_CLIENT_ID} clientSecret: ${AUTH_ONELOGIN_CLIENT_SECRET} issuer: https://<company>.onelogin.com/oidc/2 ## uncomment to set lifespan of user session # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code signIn: resolvers: # See https://backstage.io/docs/auth/onelogin/provider#resolvers for more resolvers - resolver: usernameMatchingUserEntityNameproviders.onelogin是一个结构体,包含三个核心配置键,这三个值都可在 OneLogin 应用的 SSO 标签页中找到:
clientId:OneLogin 应用的客户端 ID;clientSecret:OneLogin 应用的客户端密钥(敏感信息,建议通过环境变量注入,如${AUTH_ONELOGIN_CLIENT_SECRET});issuer:签发者 URL,形如https://<company>.onelogin.com/oidc/2。
其中issuer的<company>需要替换为你 OneLogin 租户的子域。issuer直接决定了授权端点与令牌端点地址——这一点可由源码与测试印证:authenticator.ts中issuer被原样传给OneLoginStrategy(authenticator.ts),而测试断言启动时跳转的地址为https://my-company.onelogin.com/oidc/2/auth(module.test.ts)。
可选配置:sessionDuration
sessionDuration:用户会话的生命周期。支持ms库的格式(如'24h'、'2 days')、ISO 8601 时长格式,以及代码中使用的 "human duration" 写法(如{ hours: 24 })。该字段在配置 schema 中的类型为HumanDuration | string(见 config.d.ts)。
配置层级与多环境说明
providers.onelogin下的第二层键(如示例中的development)对应认证环境名。Backstage 会根据本地auth.environment设置选择匹配的提供者配置,因此可以同时配置多个环境(如development、production),让单个 auth 后端服务多个环境(详见 docs/auth/index.md 中的说明)。仓库测试即使用development环境验证配置加载与登录流程(module.test.ts)。
callbackUrl(可选)
配置 schema 还允许可选字段callbackUrl(config.d.ts),用于在需要覆盖默认回调地址时显式指定。
第三步:选择 Sign-in 解析器(Resolvers)
OneLogin 提供者开箱即用地包含多个 sign-in 解析器,用于把 OneLogin 返回的用户信息映射为 Backstage Catalog 中的 User 实体:
emailMatchingUserEntityProfileEmail:将认证提供者返回的邮箱地址与 User 实体中匹配的spec.profile.email匹配;若未找到匹配会抛出NotFoundError。emailLocalPartMatchingUserEntityName:将认证提供者返回邮箱地址的本地部分(local part)(即@之前的部分)与 User 实体中匹配的name匹配;若未找到匹配会抛出NotFoundError。usernameMatchingUserEntityName:将认证提供者返回的用户名与 User 实体中匹配的name匹配;若未找到匹配会抛出NotFoundError。
:::note 多个解析器会按配置顺序依次尝试,但只有抛出NotFoundError时才跳过当前解析器继续尝试下一个。 :::
从配置 schema 看,每个解析器还支持不同的选项(config.d.ts):
emailLocalPartMatchingUserEntityName支持allowedDomains?: string[](限定允许的邮箱域名,详见 docs/auth/identity-resolver.md 中的用法示例)与dangerouslyAllowSignInWithoutUserInCatalog?: boolean;emailMatchingUserEntityProfileEmail与usernameMatchingUserEntityName支持dangerouslyAllowSignInWithoutUserInCatalog?: boolean。
dangerouslyAllowSignInWithoutUserInCatalog是一个需要谨慎使用的开关:开启后,当 Catalog 中找不到匹配用户实体时,仍允许登录并回退到以该名称构造的实体引用。从实现看,usernameMatchingUserEntityName在 OneLogin 用户资料缺少username时会直接抛出OneLogin user profile does not contain a username错误,随后通过ctx.signInWithCatalogUser按{ entityRef: { name: id } }完成 Catalog 用户匹配(resolvers.ts)。
内置解析器之外
这些内置解析器由模块注册时与commonSignInResolvers(通用解析器)合并提供(module.ts)。如果内置解析器无法满足需求,可以构建自定义解析器,具体做法见 docs/auth/identity-resolver.md 的 "Building Custom Resolvers" 章节。
第四步:后端安装与注册
将 OneLogin 提供者添加到后端,需要先安装对应包(在 Backstage 仓库根目录下执行):
yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-onelogin-provider然后在packages/backend/src/index.ts中添加如下代码:
backend.add(import('@backstage/plugin-auth-backend')); backend.add(import('@backstage/plugin-auth-backend-module-onelogin-provider'));从源码层面看,该模块通过createBackendModule定义,pluginId为auth、moduleId为onelogin-provider,在初始化阶段向authProvidersExtensionPoint注册providerId: 'onelogin'的提供者工厂(module.ts)。因此注册后,auth 后端会暴露/api/auth/onelogin相关端点。
底层认证流程(源码视角)
oneLoginAuthenticator基于createOAuthAuthenticator构建,其关键行为(authenticator.ts):
initialize:读取clientId、clientSecret、issuer三个必填配置,构造OneLoginStrategy;start:强制设置 OAuth scope 为openid,并附带accessType: 'offline'、prompt: 'consent'参数发起授权跳转;refresh:刷新令牌时同样把 scope 固定为openid。
仓库测试验证了整个启动流程(module.test.ts):请求/api/auth/onelogin/start?env=development返回 302 跳转到https://my-company.onelogin.com/oidc/2/auth,携带response_type=code、scope=openid、client_id、redirect_uri(指向handler/frame)及加密state参数,同时设置onelogin-noncecookie——这正是 OIDC 授权码流程的标准行为,可作为验证后端配置是否生效的参考。
第五步:前端登录页接入
前端需要把提供者接入登录页。在packages/app/src/App.tsx中引入oneloginAuthApiRef引用和SignInPage组件,参照 docs/auth/index.md 的 "Sign-in Configuration" 章节,将示例中的githubAuthApiRef替换为oneloginAuthApiRef即可,其余写法对内置提供者通用。完整示例(以新前端系统SignInPageBlueprint写法为例,同样来自 docs/auth/index.md):
import { createApp } from '@backstage/frontend-defaults'; import { oneloginAuthApiRef } from '@backstage/core-plugin-api'; import { SignInPageBlueprint } from '@backstage/plugin-app-react'; import { SignInPage } from '@backstage/core-components'; import { createFrontendModule } from '@backstage/frontend-plugin-api'; const signInPage = SignInPageBlueprint.make({ params: { loader: async () => props => ( <SignInPage {...props} provider={{ id: 'onelogin-auth-provider', title: 'OneLogin', message: 'Sign in using OneLogin', apiRef: oneloginAuthApiRef, }} /> ), }, }); export default createApp({ features: [ /* ...其他插件... */ createFrontendModule({ pluginId: 'app', extensions: [signInPage], }), ], });oneloginAuthApiRef定义于@backstage/core-plugin-api的 API 定义文件中(见 packages/core-plugin-api/src/apis/definitions/auth.ts),与前端的 auth API 实现相配套。若希望支持多登录方式(如同时提供 Guest 登录),可使用SignInPage的providers数组属性;也可通过app-config.yaml中的配置条件渲染登录提供者(详见 docs/auth/index.md 的 "Using Multiple Providers" 与 "Conditionally Render Sign In Provider" 小节)。
常见问题与排错要点
- 回调地址不匹配:
Redirect URIs必须与auth.environment对应的后端地址一致,默认开发环境为http://localhost:7007/api/auth/onelogin/handler/frame;若前端端口或后端端口变更,需同步修改 OneLogin 后台与配置。 - 环境选择错误:
providers.onelogin下的配置键(development、production)需与auth.environment匹配,否则会提示找不到对应环境的提供者配置。 - 令牌端点认证方式:OneLogin 应用的
Token Endpoint > Authentication Method必须设为POST,否则授权码换令牌环节会失败。 - 无法登录 / 404:确认后端已同时注册
@backstage/plugin-auth-backend与@backstage/plugin-auth-backend-module-onelogin-provider两个模块,缺少任一模块都会导致端点不可用。 - 用户匹配失败:检查所选 resolver 与 Catalog 中 User 实体的
name、spec.profile.email是否一致;多个 resolver 会按顺序尝试,若全部抛出NotFoundError则登录失败,可通过dangerouslyAllowSignInWithoutUserInCatalog(慎用)允许无实体登录。 - 密钥安全:
clientSecret在配置 schema 中被标记为@visibility secret(config.d.ts),应通过环境变量注入并避免明文落入版本库。
小结
接入 OneLogin 认证提供者共五步:在 OneLogin 后台创建 OIDC 应用 → 在app-config.yaml中配置clientId/clientSecret/issuer→ 配置 sign-in 解析器 → 安装并注册后端模块 → 在前端App.tsx中接入oneloginAuthApiRef与SignInPage。整个过程既有标准的 OIDC 协议支撑(passport-onelogin-oauth策略 + 授权码流程),又有 Backstage 新后端系统模块化注册机制作为底座。如需更深入理解 sign-in 身份映射机制,可继续阅读 docs/auth/identity-resolver.md;如需了解其他内置提供者的接入方式,可查阅 docs/auth/index.md 与 docs/auth/ 目录下的各提供者文档。
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考