使用 SAML 登录用户
本文档介绍如何使用 Identity Platform 让用户通过安全断言标记语言 (SAML) 2.0 提供方登录。
准备工作
- 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
- 启用 Identity Platform,并将 Client SDK 添加到您的应用。如需了解具体方法,请参阅快速入门。
配置提供商
前往 Google Cloud 控制台中的身份提供商页面。
转到“身份提供商”页面点击添加提供商,然后从列表中选择 SAML。
输入以下详细信息:
提供商的名称。它可以与提供商 ID 相同,也可以是自定义名称。如果要输入自定义名称,请点击提供商 ID 旁边的修改以指定 ID(必须以
saml.
开头)。提供商的实体 ID。
提供商的 SAML SSO 网址。
用于对提供商进行令牌签名的证书。请确保包含开始字符串和结束字符串。例如:
-----BEGIN CERTIFICATE----- MIICajCCAdOgAwIBAgIBADANBgkqhkiG9w0BAQ0FADBSMQswCQYDVQQGEwJ1czEL ... LEzc1JwEGQQVDYQCwsQMSBDAF0QAB0w9GikhqkgBNADABIgABIwAgOdACCjaCIIM -----END CERTIFICATE-----
在服务提供商下,输入应用的实体 ID。这通常是您的应用的网址。SAML 身份提供商称之为受众。
将您的应用添加到已获授权的网域列表中。例如,如果应用的登录网址为
https://example.com/login
,请添加example.com
。如有需要,您可以为应用自定义回调网址。SAML 身份提供商通常称之为断言消费者服务 (ACS) 网址。
使用默认回调网址可以降低验证 SAML 响应的复杂程度。如果您要自定义此流程,请确保为 SAML 身份提供商配置项目的 Identity Platform 回调网址。它的格式通常为
https://[PROJECT-ID].firebaseapp.com/__/auth/handler
。如需了解详情,请参阅自定义身份验证处理程序。点击保存。
提供方必需的元素
Identity Platform 需要提供商的响应中包含 <saml:Subject>
和 <saml:NameID>
元素。
如果您在配置提供程序时未为这些元素定义值,SAML 断言将会失败。
对请求进行签名
您可以通过对身份验证请求进行签名来增强其安全性。
要对请求进行签名,首先需要为您的身份提供商启用签名请求,方法是调用 inboundSamlConfigs.patch()
并将 idp_config.sign_request
设置为 true
:
REST
在使用任何请求数据之前,请先进行以下替换:
project-id
:Google Cloud 项目的 IDprovider-id
:SAML 提供方 ID
HTTP 方法和网址:
PATCH https://identitytoolkit.googleapis.com/admin/v2/projects/project-id/inboundSamlConfigs/provider-id?updateMask=idpConfig.signRequest
请求 JSON 正文:
{ "idp_config": { "sign_request": true } }
如需发送您的请求,请展开以下选项之一:
您必须使用 REST API 启用已签名的请求;使用 不支持 Google Cloud 控制台或 Google Cloud CLI。
响应是一个 InboundSamlConfig
对象,它包含一组 SpCertificate
。
使用您的 SAML 身份提供商配置 X509 证书的值,以便它能够验证请求的签名。
登录用户
当用户登录时,Client SDK 会处理身份验证握手,然后返回载荷中包含 SAML 特性的 ID 令牌。要登录用户并从 SAML 提供商获取特性,请执行以下操作:
使用您在上一部分中配置的提供商 ID 创建
SAMLAuthProvider
实例。提供商 ID 必须以saml.
开头。Web 版本 9
import { SAMLAuthProvider } from "firebase/auth"; const provider = new SAMLAuthProvider("saml.myProvider");
Web 版本 8
const provider = new firebase.auth.SAMLAuthProvider('saml.myProvider');
启动登录流程。您可以选择使用弹出式窗口或重定向。
弹出式内容
Web 版本 9
import { getAuth, signInWithPopup, SAMLAuthProvider } from "firebase/auth"; const auth = getAuth(); signInWithPopup(auth, provider) .then((result) => { // User is signed in. // Provider data available from the result.user.getIdToken() // or from result.user.providerData }).catch((error) => { // Handle Errors here. const errorCode = error.code; const errorMessage = error.message; // The email of the user's account used. const email = error.customData.email; // The AuthCredential type that was used. const credential = SAMLAuthProvider.credentialFromError(error); // Handle / display error. // ... });
Web 版本 8
firebase.auth().signInWithPopup(provider) .then((result) => { // User is signed in. // Identity provider data available in result.additionalUserInfo.profile, // or from the user's ID token obtained from result.user.getIdToken() // as an object in the firebase.sign_in_attributes custom claim // This is also available from result.user.getIdTokenResult() // idTokenResult.claims.firebase.sign_in_attributes. }) .catch((error) => { // Handle / display error. // ... });
重定向
如需重定向到登录页面,请调用
signInWithRedirect()
:Web 版本 9
import { getAuth, signInWithRedirect } from "firebase/auth"; const auth = getAuth(); signInWithRedirect(auth, provider);
Web 版本 8
firebase.auth().signInWithRedirect(provider);
然后,调用
getRedirectResult()
以在用户返回您的应用时获取结果:Web 版本 9
import { getAuth, getRedirectResult, SAMLAuthProvider } from "firebase/auth"; const auth = getAuth(); getRedirectResult(auth) .then((result) => { // User is signed in. // Provider data available from the result.user.getIdToken() // or from result.user.providerData }) .catch((error) => { // Handle Errors here. const errorCode = error.code; const errorMessage = error.message; // The email of the user's account used. const email = error.customData.email; // The AuthCredential type that was used. const credential = SAMLAuthProvider.credentialFromError(error); // Handle / display error. // ... });
Web 版本 8
firebase.auth().getRedirectResult() .then((result) => { // User is signed in. // Provider data available in result.additionalUserInfo.profile, // or from the user's ID token obtained from result.user.getIdToken() // as an object in the firebase.sign_in_attributes custom claim // This is also available from result.user.getIdTokenResult() // idTokenResult.claims.firebase.sign_in_attributes. }).catch((error) => { // Handle / display error. // ... });
使用
firebase.sign_in_attributes
声明从 ID 令牌中检索与 SAML 提供商相关的用户特性。在将 ID 令牌 发送到服务器时,务必使用 Admin SDK 验证 ID 令牌。只有当用户的电子邮件地址在 ID 令牌中 身份提供方的 SAML 断言的
NameID
属性:<Subject> <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">test@email.com</NameID> </Subject>
此值会填充在 Firebase 签发的 ID 令牌和 UserInfo 对象中。
目前仅支持服务提供商通过 Client SDK 启动的 SAML 流程。
关联用户账号
如果用户已使用其他方法(例如电子邮件/密码)登录到应用,您可以使用 linkWithPopup()
或 linkWithRedirect()
将其现有账号关联到 SAML 提供商:
例如,我们可以使用 Google 账号进行关联:
Web 版本 9
import { getAuth, linkWithPopup, GoogleAuthProvider } from "firebase/auth"; const provider = new GoogleAuthProvider(); const auth = getAuth(); linkWithPopup(auth.currentUser, provider).then((result) => { // Accounts successfully linked. const credential = GoogleAuthProvider.credentialFromResult(result); const user = result.user; // ... }).catch((error) => { // Handle Errors here. // ... });
Web 版本 8
auth.currentUser.linkWithPopup(provider).then((result) => { // Accounts successfully linked. var credential = result.credential; var user = result.user; // ... }).catch((error) => { // Handle Errors here. // ... });