使用 OIDC 登录用户

本文档介绍如何使用 Identity Platform 让用户通过 OpenID Connect (OIDC) 提供商登录。

准备工作

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  3. 确保您的 Google Cloud 项目已启用结算功能

  4. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  5. 确保您的 Google Cloud 项目已启用结算功能

  6. 启用 Identity Platform,并将 Client SDK 添加到您的应用。如需了解具体方法,请参阅快速入门

配置提供商

  1. 前往 Google Cloud 控制台中的身份提供方页面。
    转到“身份提供商”页面

  2. 点击添加提供商,然后从列表中选择 OpenID Connect

授权码流程

  1. 输入以下详细信息以启用授权码流程:

    1. 选择授权类型部分下,选择代码流

    2. 提供商的名称。它可以与提供商 ID 相同,也可以是自定义名称。如果要输入自定义名称,请点击提供商 ID 旁边的修改以指定 ID(必须以 oidc. 开头)。

    3. 提供商的客户端 ID

    4. 提供商的颁发者。其格式应类似于 https://example.com。Identity Platform 使用此网址查找 OIDC 发现文档(通常位于 /.well-known/openid-configuration),该文档指定了提供商的 OAuth 端点和公钥。

    5. 提供商的客户端密钥

  2. 将您的应用添加到已获授权的网域列表中。例如,如果应用的登录网址为 https://example.com/login,请添加 example.com

  3. 将 Identity Platform 回调网址配置为您的 OIDC 提供商的重定向网址。网址应类似于 https://[PROJECT-ID].firebaseapp.com/__/auth/handler

  4. 点击保存

隐式流程

  1. 输入以下详细信息以启用隐式流程:

    1. 选择授权类型部分下,选择隐式流程

    2. 提供商的名称。它可以与提供商 ID 相同,也可以是自定义名称。如果要输入自定义名称,请点击提供商 ID 旁边的修改以指定 ID(必须以 oidc. 开头)。

    3. 提供商的客户端 ID

    4. 提供商的颁发者。这应如下所示:https://example.com. Identity Platform 使用此网址来查找 OIDC 发现文档(通常位于 /.well-known/openid-configuration),该文档指定了提供商的 OAuth 端点和公开键。

  2. 将您的应用添加到已获授权的网域列表中。例如,如果应用的登录网址为 https://example.com/login,请添加 example.com

  3. 将 Identity Platform 回调网址配置为您的 OIDC 提供商的重定向网址。网址应类似于 https://[PROJECT-ID].firebaseapp.com/__/auth/handler

  4. 点击保存

登录用户

您可以使用两种方法让用户通过 OIDC 登录:

  • 使用 OAuth 流程。此方法会为您完成 OAuth 握手。根据配置提供商步骤中的授权代码l流程/隐式流程选择,GCIP 服务器选择所需的流程来与身份提供商通信。

  • 使用 OIDC 提供商的 ID 令牌。此方法假定您已有 OIDC 令牌。

让用户通过 OAuth 登录

要使用 OAuth 登录,请执行以下操作:

  1. 使用您在上一部分中配置的提供商 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');
  2. 启动登录流程。您可以选择使用弹出式窗口或重定向。

    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 令牌登录,请执行以下操作:

  1. 使用您在上一部分中配置的提供方 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.
  // ...
});

后续步骤