Logto 是一个为现代应用和 SaaS 产品设计的 Auth0 替代方案。它提供 Cloud 和 开源 服务,帮助你快速启动身份和管理 (IAM) 系统。享受认证 (Authentication)、授权 (Authorization) 和多租户管理 一体化。
我们建议从 Logto Cloud 上的免费开发租户开始。这可以让你轻松探索所有功能。
在本文中,我们将介绍使用 React 和 Logto 快速构建 SAML 登录体验(用户认证 (Authentication))的步骤。
先决条件
在 Logto 中创建一个应用程序
Logto 基于 OpenID Connect (OIDC) 认证 (Authentication) 和 OAuth 2.0 授权 (Authorization)。它支持跨多个应用程序的联合身份管理,通常称为单点登录 (SSO)。
要创建你的 单页应用 应用程序,只需按照以下步骤操作:
- 打开 Logto Console。在“开始使用”部分,点击“查看全部”链接以打开应用程序框架列表。或者,你可以导航到 Logto Console > Applications,然后点击“创建应用程序”按钮。
- 在打开的模态窗口中,点击“单页应用”部分,或使用左侧的快速过滤复选框过滤所有可用的“单页应用”框架。点击 "React" 框架卡片以开始创建你的应用程序。
- 输入应用程序名称,例如“Bookstore”,然后点击“创建应用程序”。
🎉 太棒了!你刚刚在 Logto 中创建了你的第一个应用程序。你将看到一个祝贺页面,其中包含详细的集成指南。按照指南查看你的应用程序中的体验将会是什么样的。
集成 React SDK
- 示例项目可在我们的 SDK 仓库 中找到。
- 教程视频可在我们的 YouTube 频道 上观看。
安装
通过你喜欢的包管理器安装 Logto SDK:
- npm
- pnpm
- yarn
npm i @logto/react
pnpm add @logto/react
yarn add @logto/react
初始化 LogtoClient
将 LogtoProvider
导入并用于为你的应用提供一个 Logto 上下文:
import { LogtoProvider, LogtoConfig } from '@logto/react';
const config: LogtoConfig = {
endpoint: '<your-logto-endpoint>', // 例如 http://localhost:3001
appId: '<your-application-id>',
};
const App = () => (
<LogtoProvider config={config}>
<YourAppContent />
</LogtoProvider>
);
配置重定向 URI
在我们深入细节之前,这里是终端用户体验的快速概述。登录过程可以简化如下:
- 你的应用调用登录方法。
- 用户被重定向到 Logto 登录页面。对于原生应用,将打开系统浏览器。
- 用户登录并被重定向回你的应用(配置为重定向 URI)。
关于基于重定向的登录
- 此认证 (Authentication) 过程遵循 OpenID Connect (OIDC) 协议,Logto 强制执行严格的安全措施以保护用户登录。
- 如果你有多个应用程序,可以使用相同的身份提供商 (IdP)(日志 (Logto))。一旦用户登录到一个应用程序,当用户访问另一个应用程序时,Logto 将自动完成登录过程。
要了解有关基于重定向的登录的原理和好处的更多信息,请参阅 Logto 登录体验解释。
在以下代码片段中,我们假设你的应用程序运行在 http://localhost:3000/
。
配置重定向 URI
切换到 Logto Console 的应用详情页面。添加一个重定向 URI http://localhost:3000/callback
。
就像登录一样,用户应该被重定向到 Logto 以注销共享会话。完成后,最好将用户重定向回你的网站。例如,添加 http://localhost:3000/
作为注销后重定向 URI 部分。
然后点击“保存”以保存更改。
处理重定向
由于我们使用 http://localhost:3000/callback
作为重定向 URI,现在我们需要正确处理它。
首先,让我们创建一个回调页面:
import { useHandleSignInCallback } from '@logto/react';
const Callback = () => {
const { isLoading } = useHandleSignInCallback(() => {
// 完成后执行某些操作,例如重定向到主页
});
// 当它正在处理中
if (isLoading) {
return <div>正在重定向...</div>;
}
return null;
};
最后插入下面的代码来创建一个不需要认证 (Authentication) 的 /callback
路由:
// 假设使用 react-router
<Route path="/callback" element={<Callback />} />
实现登录和登出
我们提供了两个钩子 useHandleSignInCallback()
和 useLogto()
,可以帮助你轻松管理认证 (Authentication) 流程。
在调用 .signIn()
之前,请确保你已在管理控制台中正确配置了重定向 URI。
import { useLogto } from '@logto/react';
const Home = () => {
const { signIn, signOut, isAuthenticated } = useLogto();
return isAuthenticated ? (
<button onClick={signOut}>Sign Out</button>
) : (
<button onClick={() => signIn('http://localhost:3000/callback')}>Sign In</button>
);
};
调用 .signOut()
将清除内存和 localStorage 中所有的 Logto 数据(如果存在)。
检查点:测试你的应用程序
现在,你可以测试你的应用程序:
- 运行你的应用程序,你将看到登录按钮。
- 点击登录按钮,SDK 将初始化登录过程并将你重定向到 Logto 登录页面。
- 登录后,你将被重定向回你的应用程序,并看到登出按钮。
- 点击登出按钮以清除令牌存储并登出。
添加 SAML 连接器
要实现快速登录并提高用户转化率,请将 React 作为身份提供商 (IdP) 进行连接。Logto 社交连接器可以帮助你在几分钟内通过允许输入多个参数来建立此连接。
要添加社交连接器,只需按照以下步骤操作:
- 导航到 Console > Connectors > Social Connectors。
- 点击“添加社交连接器”并选择“SAML”。
- 按照 README 指南完成必填字段并自定义设置。
如果你正在按照现场连接器指南进行操作,可以跳过下一部分。
设置 标准 SAML 应用
创建社交 IdP 的账户并注册 SAML 应用程序 (IdP)
让我们来看看 SAML 连接器的配置。
在开始之前,你可以去支持 SAML 协议的社交身份提供商创建自己的账户。Okta、OneLogin、Salesforce 和其他一些平台支持基于 SAML 协议的认证 (Authentication)。
如果你的 IdP 要求对 SAML 断言进行加密并接收签名的认证请求,你应该使用 RSA 算法生成你的私钥和相应的证书。保留私钥供你的 SP 使用,并将证书上传到 IdP。
你还需要将 ACS (Assertion Consumer Service) URL 配置为 ${your_logto_origin}/api/authn/saml/${connector_id}
以处理 IdP 的 SAML 断言。你可以在 Logto 管理控制台的 SAML 连接器详细信息页面找到你的 connectorId
。
根据当前 Logto 的设计,我们仅支持用于发送认证请求的重定向绑定和用于接收 SAML 断言的 POST 绑定。虽然这听起来不太酷,但我们相信当前的设计可以处理大多数用例。如果你有任何问题,请随时联系我们!
配置 SAML 连接器 (SP)
在本节中,我们将详细介绍每个属性。
entityID 必需
entityID
(即 issuer
)是实体标识符。它用于识别你的实体(SAML SP 实体),并在每个 SAML 请求/响应中匹配等效项。
signInEndpoint 必需
你发送 SAML 认证请求的 IdP 端点。通常,你可以在 IdP 详细信息页面找到此值(即 IdP 的 SSO URL
或 Login URL
)。
x509Certificate 必需
从 IdP 私钥生成的 x509 证书,IdP 应该提供此值。
证书的内容带有 -----BEGIN CERTIFICATE-----
头和 -----END CERTIFICATE-----
尾。
idpMetadataXml 必需
此字段用于放置来自 IdP 元数据 XML 文件的内容。
我们使用的 XML 解析器不支持自定义命名空间。 如果 IdP 元数据带有命名空间,你应该手动删除它们。 有关 XML 文件的命名空间,请参阅 参考。
assertionConsumerServiceUrl 必需
断言消费者服务 (ACS) URL 是 SP 接收 IdP 的 SAML 断言 POST 请求的端点。如我们在前面部分提到的,它通常在 IdP 设置中配置,但有些 IdP 从 SAML 认证请求中获取此值,因此我们也将此值添加为必需字段。它的值应类似于 ${your_logto_origin}/api/authn/saml/${connector_id}
。
signAuthnRequest
控制 SAML 认证请求是否应签名的布尔值,默认值为 false
。
encryptAssertion
encryptAssertion
是一个布尔值,指示 IdP 是否会加密 SAML 断言,默认值为 false
。
signAuthnRequest
和 encryptAssertion
属性应与 IdP 设置的相应参数一致,否则会抛出错误,显示配置不匹配。
所有 SAML 响应都需要签名。
requestSignatureAlgorithm
这应该与 IdP 的签名算法一致,以便 Logto 可以验证 SAML 断言的签名。其值应为 http://www.w3.org/2000/09/xmldsig#rsa-sha1
、http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
或 http://www.w3.org/2001/04/xmldsig-more#rsa-sha512
,默认值为 http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
。
messageSigningOrder
messageSigningOrder
指示 IdP 的签名和加密顺序,其值应为 sign-then-encrypt
或 encrypt-then-sign
,默认值为 sign-then-encrypt
。
privateKey 和 privateKeyPass
privateKey
是一个可选值,当 signAuthnRequest
为 true
时是必需的。
privateKeyPass
是你在创建 privateKey
时设置的密码,必要时需要。
如果 signAuthnRequest
为 true
,则 IdP 需要从 privateKey
生成的相应证书来检查签名。
encPrivateKey 和 encPrivateKeyPass
encPrivateKey
是一个可选值,当 encryptAssertion
为 true
时是必需的。
encPrivateKeyPass
是你在创建 encPrivateKey
时设置的密码,必要时需要。
如果 encryptAssertion
为 true
,则 IdP 需要从 encPrivateKey
生成的相应证书来加密 SAML 断言。
对于密钥和证书的生成,openssl
是一个很好的工具。以下是可能有用的示例命令行:
openssl genrsa -passout pass:${privateKeyPassword} -out ${encryptPrivateKeyFilename}.pem 4096
openssl req -new -x509 -key ${encryptPrivateKeyFilename}.pem -out ${encryptionCertificateFilename}.cer -days 3650
privateKey
和 encPrivateKey
文件被强制编码为 pkcs1
方案的 pem 字符串,这意味着私钥文件应以 -----BEGIN RSA PRIVATE KEY-----
开头并以 -----END RSA PRIVATE KEY-----
结尾。
nameIDFormat
nameIDFormat
是一个可选属性,用于声明响应的名称 ID 格式。其值可以是 urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
、urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
、urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
、urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
和 urn:oasis:names:tc:SAML:2.0:nameid-format:transient
,默认值为 urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified
。
timeout
timeout
是时间验证的时间容差,因为你的 SP 实体和 IdP 实体之间的时间可能不同,网络连接也可能带来一些延迟。单位为毫秒,默认值为 5000(即 5 秒)。
profileMap
Logto 还提供了一个 profileMap
字段,用户可以自定义从社交供应商的配置文件中映射,这些配置文件通常不是标准的。每个 profileMap
键是 Logto 的标准用户配置文件字段名称,相应的值应为社交配置文件字段名称。在当前阶段,Logto 只关注社交配置文件中的 'id'、'name'、'avatar'、'email' 和 'phone',其中只有 'id' 是必需的,其他是可选字段。
配置类型
名称 | 类型 | 必需 | 默认值 |
---|---|---|---|
signInEndpoint | string | true | |
x509certificate | string | true | |
idpMetadataXml | string | true | |
entityID | string | true | |
assertionConsumerServiceUrl | string | true | |
messageSigningOrder | encrypt-then-sign | sign-then-encrypt | false | sign-then-encrypt |
requestSignatureAlgorithm | http://www.w3.org/2000/09/xmldsig#rsa-sha1 | http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 | http://www.w3.org/2001/04/xmldsig-more#rsa-sha512 | false | http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 |
signAuthnRequest | boolean | false | false |
encryptAssertion | boolean | false | false |
privateKey | string | false | |
privateKeyPass | string | false | |
nameIDFormat | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress | urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName | urn:oasis:names:tc:SAML:2.0:nameid-format:persistent | urn:oasis:names:tc:SAML:2.0:nameid-format:transient | false | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified |
timeout | number | false | 5000 |
profileMap | ProfileMap | false |
ProfileMap 字段 | 类型 | 必需 | 默认值 |
---|---|---|---|
id | string | false | id |
name | string | false | name |
avatar | string | false | avatar |
string | false | ||
phone | string | false | phone |
参考
保存你的配置
仔细检查你是否在 Logto 连接器配置区域填写了必要的值。点击“保存并完成”(或“保存更改”),SAML 连接器现在应该可用了。
在登录体验中启用 SAML 连接器
一旦你成功创建了一个社交连接器,你可以在登录体验中将其启用为“继续使用 SAML”按钮。
- 导航到 Console > 登录体验 > 注册和登录。
- (可选)如果只需要社交登录,选择“无”作为注册标识符。
- 将配置好的 SAML 连接器添加到“社交登录”部分。
测试和验证
返回到你的 React 应用。你现在应该可以使用 SAML 登录了。享受吧!
拓展阅读
终端用户流程:Logto 提供开箱即用的认证 (Authentication) 流程,包括多因素认证 (MFA) 和企业单点登录 (SSO),以及强大的 API,用于灵活实现账户设置、安全验证和多租户体验。
授权 (Authorization):授权 (Authorization) 定义了用户在被认证 (Authentication) 后可以执行的操作或访问的资源。探索如何保护你的 API 以用于原生和单页应用程序,并实现基于角色的访问控制 (RBAC)。
组织 (Organizations):在多租户 SaaS 和 B2B 应用中特别有效,组织功能支持租户创建、成员管理、组织级 RBAC 和即时供应。
客户 IAM 系列:我们关于客户(或消费者)身份和访问管理的系列博客文章,从 101 到高级主题及更深入的内容。