跳转至

账号关联

当您为已有用户的应用添加社交登录时,部分用户会点击 使用 Google 继续,尽管他们最初是用邮箱和密码注册的。这两种身份使用同一个邮箱地址,但默认情况下,Authany 会把这次 Google 注册当作创建第二个账号的尝试,并以「账号已存在」错误拒绝该请求。

账号关联改变了后续的处理方式。Authany 不再报错,而是检测到新接入的 Google 账号与现有用户匹配,要求用户登录该账号一次以证明所有权,然后将 Google 身份关联到该账号。最终用户只有一个账号,但拥有两种登录方式。

说明

账号关联会在注册过程中自动执行。如果想让已登录的用户通过您自己的界面连接某个提供方,请参阅使用 SDK 关联和取消关联社交/企业登录提供方。用户也可以在用户设置页面管理自己的连接。

何时使用

当同一个人可以通过多种注册方式访问您的应用,并且您希望他们始终只保留一个账号时,请启用账号关联。常见场景包括:

  • 您为已有密码用户的应用添加了 Google 登录。 使用 alice@example.com 和密码注册的用户点击了 使用 Google 继续。他们的 Google 账号使用相同的邮箱。启用账号关联后,用户只需用密码登录一次,此后就可以用任意一种方式登录。
  • 您提供了多个社交登录提供方。 用户今天用 Google 注册,下个月又在手机上点击了 使用 Apple 继续。两个账号共用同一个邮箱;账号关联可以让它们合并为一个 Authany 账号,而不是变成两个。
  • 您将用户迁移到了 Authany,之后又启用了企业登录提供方。 导入的用户会按邮箱与其 Microsoft Entra ID 或 ADFS 账号匹配,因此他们首次使用企业登录时会关联到您导入的账号,而不会新建一个账号。

工作原理

当用户通过社交或企业登录提供方注册时,Authany 会从该提供方的用户资料中读取一个声明(默认是邮箱),并与现有用户的身份进行比对。匹配成功后的处理方式取决于您配置的 action:

Action 行为
error 以「重复身份」错误拒绝该次注册。这是未配置账号关联时的默认行为。
login_and_link 向用户展示其现有账号,并要求登录该账号。用户完成身份验证后,将新的提供方身份关联到该账号,并继续完成注册。

注意

login_and_link 中的登录步骤可以防止账号被劫持。有些身份提供方允许任何人使用未验证的邮箱注册,因此仅凭邮箱匹配并不能证明所有权。如果没有登录步骤,攻击者就可以在这类提供方上注册 alice@example.com,从而劫持 Alice 的账号。

启用账号关联

本教程以 Google 为例,但同样的配置方法适用于您已设置的任何提供方。

前提条件

  • 已在管理台的 身份验证 > 社交 / 企业登录 中配置好 Google 登录提供方,并设置了别名(alias)。本指南假设别名为 google。如果尚未完成该设置,请参阅将应用连接到 Google。

添加配置

在项目的 YAML 配置中配置账号关联。在管理台中进入 高级 > 编辑配置,添加一个 account_linking 部分:

account_linking:
  oauth:
    - alias: google
      oauth_claim:
        pointer: "/email"
      user_profile:
        pointer: "/email"
      action: login_and_link

保存配置,更改会立即生效。

account_linking.oauth 下的每一项都定义一条关联规则:

Field 含义
alias 该规则适用的提供方。必须与 社交 / 企业登录 中某个提供方的别名一致。
oauth_claim 指向要从接入的提供方资料中读取的声明的 JSON 指针。/email 表示读取 Google 返回的邮箱。
user_profile 指向要与现有用户身份进行匹配的属性的 JSON 指针。/email 表示匹配邮箱登录 ID 或标准属性相同的用户。
action 匹配成功后的处理方式:error 或 login_and_link。

说明

oauth_claim 和 user_profile 仅支持 /email、/phone_number 和 /preferred_username。按邮箱匹配适用于 Google 和大多数社交登录提供方;/preferred_username 则适合像 ADFS 这类按用户名识别用户的企业登录提供方。

用户体验到的流程

配置好上述内容后,对于已经使用 alice@example.com 拥有密码账号的用户,完整流程如下:

  1. 用户在注册页面点击 使用 Google 继续,并完成 Google 的授权同意页。
  2. Authany 找到该现有账号,并展示 找到现有账号 页面,列出经过掩码处理的标识符,例如 al***@example.com。
  3. 用户选择该账号,并使用现有方式登录,本例中为密码。
  4. Authany 将 Google 身份关联到该账号。如果您的注册流程要求完成该账号尚未满足的步骤(例如设置双重验证),用户此时需要完成这些步骤;账号已经满足的步骤则会被跳过。
  5. 用户完成登录。此后,密码和 Google 都可以登录到同一个账号。

关联邮箱、手机号或用户名注册

账号关联同样支持反向场景:用户先用 Google 注册,之后又尝试用相同的邮箱地址和密码注册。请在 account_linking.login_id 下配置:

account_linking:
  login_id:
    - key: email
      user_profile:
        pointer: "/email"
      action: login_and_link

key 用于指定登录 ID 类型(默认为 email、phone 或 username)。当使用该登录 ID 注册的请求与现有用户匹配时,用户会登录到现有账号(本例中通过 Google 登录),新的邮箱登录 ID 会被添加到该账号。如果不做此配置,冲突的注册请求会像之前一样以错误失败。

进阶:为不同注册流程设置不同规则

如果您定义了自定义身份验证流程,可以在特定的注册流程步骤中覆盖某条关联规则。先在 account_linking 中为规则设置一个 name,再在该步骤中引用这个名称,以覆盖其 action 或指定由哪个登录流程来处理登录:

account_linking:
  oauth:
    - name: google_linking
      alias: google
      oauth_claim:
        pointer: "/email"
      user_profile:
        pointer: "/email"
      action: error
authentication_flow:
  signup_flows:
    - name: customer_signup
      steps:
        - name: identify
          type: identify
          one_of:
            - identification: oauth
              account_linking:
                oauth:
                  - name: google_linking
                    action: login_and_link
                    login_flow: customer_login

在此示例中,除 customer_signup 流程外,Google 关联在其他任何地方都会以错误失败;该流程允许关联,并在登录步骤中运行 customer_login 流程。如果未设置 login_flow,Authany 会使用与当前注册流程同名的登录流程。

自定义界面中的账号关联

如果您使用身份验证流程 API构建自己的注册界面,账号关联会表现为一个 identify 动作,其 data.type 为 account_linking_identification_data。数据中包含匹配到的账号列表及其经过掩码处理的显示名称;您的界面需要提交用户所选账号的索引,随后流程会继续进入登录步骤。具体的数据结构请参阅身份验证流程 API 参考。