使用 OIDC 登录用户
本文档介绍如何使用 Identity Platform 让用户通过 OpenID Connect (OIDC) 提供商登录。
准备工作
- 登录您的 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 控制台中的身份提供商页面。
转到“身份提供商”页面点击添加提供商,然后从列表中选择 OpenID Connect。
授权码流程
输入以下详细信息以启用授权码流程:
在选择授权类型部分下,选择代码流。
提供商的名称。它可以与提供商 ID 相同,也可以是自定义名称。如果要输入自定义名称,请点击提供商 ID 旁边的修改以指定 ID(必须以
oidc.
开头)。提供商的客户端 ID。
提供商的颁发者。其格式应类似于
https://example.com
。Identity Platform 使用此网址查找 OIDC 发现文档(通常位于/.well-known/openid-configuration
),该文档指定了提供商的 OAuth 端点和公钥。提供商的客户端密钥。
将您的应用添加到已获授权的网域列表中。例如,如果应用的登录网址为
https://example.com/login
,请添加example.com
。将 Identity Platform 回调网址配置为您的 OIDC 提供商的重定向网址。网址应类似于
https://[PROJECT-ID].firebaseapp.com/__/auth/handler
。点击保存。
隐式流程
输入以下详细信息以启用隐式流程:
在选择授权类型部分下,选择隐式流程。
提供商的名称。它可以与提供商 ID 相同,也可以是自定义名称。如果要输入自定义名称,请点击提供商 ID 旁边的修改以指定 ID(必须以
oidc.
开头)。提供商的客户端 ID。
提供商的颁发者。这应如下所示:
https://example.com.
Identity Platform 使用此网址来查找 OIDC 发现文档(通常位于/.well-known/openid-configuration
),该文档指定了提供商的 OAuth 端点和公开键。
将您的应用添加到已获授权的网域列表中。例如,如果应用的登录网址为
https://example.com/login
,请添加example.com
。将 Identity Platform 回调网址配置为您的 OIDC 提供商的重定向网址。网址应类似于
https://[PROJECT-ID].firebaseapp.com/__/auth/handler
。点击保存。
登录用户
您可以使用两种方法让用户通过 OIDC 登录:
使用 OAuth 流程。此方法会为您完成 OAuth 握手。根据配置提供商步骤中的授权代码l流程/隐式流程选择,GCIP 服务器选择所需的流程来与身份提供商通信。
使用 OIDC 提供商的 ID 令牌。此方法假定您已有 OIDC 令牌。
让用户通过 OAuth 登录
要使用 OAuth 登录,请执行以下操作:
使用您在上一部分中配置的提供商 ID 创建
OAuthProvider
实例。提供商 ID 必须以oidc.
开头。Web 版本 9
import { OAuthProvider } from "firebase/auth"; const provider = new OAuthProvider("oidc.myProvider");
Web 版本 8
const provider = new firebase.auth.OAuthProvider('oidc.myProvider');
启动登录流程。您可以选择使用弹出式窗口或重定向。
弹出式内容
Web 版本 9
import { getAuth, signInWithPopup, OAuthProvider } from "firebase/auth"; const auth = getAuth(); signInWithPopup(auth, provider) .then((result) => { // User is signed in. const credential = OAuthProvider.credentialFromResult(result); // This gives you an access token for the OIDC provider. You can use it to directly interact with that provider }).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 = OAuthProvider.credentialFromError(error); // Handle / display error. // ... });
Web 版本 8
firebase.auth().signInWithPopup(provider) .then((result) => { // User is signed in. // result.credential is a firebase.auth().OAuthCredential object. // result.credential.providerId is equal to 'oidc.myProvider'. // result.credential.idToken is the OIDC provider's ID token. }) .catch((error) => { // Handle error. });
重定向
如需重定向到登录页面,请调用
signInWithRedirect()
:Web 版本 9
import { getAuth, signInWithRedirect } from "firebase/auth"; const auth = getAuth(); signInWithRedirect(auth, provider);
Web 版本 8
firebase.auth().signInWithRedirect(provider).catch((error) => { // Handle error. });
然后,调用
getRedirectResult()
以在用户返回应用时获取结果:Web 版本 9
import { getAuth, getRedirectResult, OAuthProvider } from "firebase/auth"; const auth = getAuth(); getRedirectResult(auth) .then((result) => { // User is signed in. const credential = OAuthProvider.credentialFromResult(result); // This gives you an access token for the OIDC provider. You can use it to directly interact with that provider }) .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 = OAuthProvider.credentialFromError(error); // Handle / display error. // ... });
Web 版本 8
// On return. firebase.auth().getRedirectResult() .then((result) => { // User is signed in. // result.credential is a firebase.auth().OAuthCredential object. // result.credential.providerId is equal to 'oidc.myProvider'. // result.credential.idToken is the OIDC provider's ID token. }) .catch((error) => { // Handle / display error. // ... });
在任一流程结束时,您都可以使用 result.credential.idToken
字段获取 OIDC ID 令牌。
直接登录用户
如需使用 OIDC ID 令牌直接登录用户,请执行以下操作:
使用您在上一部分中配置的提供方 ID 初始化
OAuthProvider
实例。提供商 ID 必须以oidc.
开头。然后,创建OAuthCredential
,并调用signInWithCredential()
以登录用户。Web 版本 9
import { getAuth, OAuthProvider, signInWithCredential } from "firebase/auth"; const auth = getAuth(); const credential = provider.credential({ idToken: oidcIdToken, }); signInWithCredential(auth, credential) .then((result) => { // User is signed in. const newCredential = OAuthProvider.credentialFromResult(result); // This gives you a new access token for the OIDC provider. You can use it to directly interact with that provider. }) .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 = OAuthProvider.credentialFromError(error); // Handle / display error. // ... });
Web 版本 8
const credential = provider.credential(oidcIdToken, null); firebase.auth().signInWithCredential(credential) .then((result) => { // User is signed in. // User now has a odic.myProvider UserInfo in providerData. }) .catch((error) => { // Handle / display error. // ... });
关联用户账号
如果用户已使用其他方法(例如电子邮件/密码)登录到应用,您可以使用 linkWithPopup()
或 linkWithRedirect()
将其现有账号关联到 OIDC 提供商:
例如,我们可以通过以下方式关联 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. // ... });