Skip to content

OIDC 常见问题

OIDC 的全称是 OpenID Connect,是一个基于 OAuth 2.0 的轻量级认证 + 授权协议,是 OAuth 2.0 的超集。它规定了其他应用,例如你开发的应用 A(XX 邮件系统),应用 B(XX 聊天系统),应用 C(XX 文档系统),如何到你的中央数据表中取出用户数据,约定了交互方式、安全规范等,确保了你的用户能够在访问所有应用时,只需登录一遍,而不是反反复复地输入密码,而且遵循这些规范,你的用户认证环节会很安全。

OIDC 在后端如何处理

请参考 GitHub 上的示例:example-spring-boot-oidc

OIDC 三种认证流程的特征对比

特性授权码模式隐式模式混合模式
所有 token 全部从授权端点返回noyesno
所有 token 都从 token 端点返回yesnono
token 不会暴露给前端yesnono
客户端可以被 OP 认证yesnoyes
可以刷新 tokenyesnoyes
一次交互noyesno
必须服务器-服务器通信yesnovaries

不同 response-type 对应的授权流程

"response_type" valueFlow
codeAuthorization Code Flow(授权码模式)
id_tokenImplicit Flow(隐式模式)
id_token tokenImplicit Flow(隐式模式)
code id_tokenHybrid Flow(混合模式)
code tokenHybrid Flow(混合模式)
code id_token tokenHybrid Flow(混合模式)

参考 OIDC 规范

如何验证 Token 合法性

请参考:

/guides/basics/authenticate-first-user/how-to-validate-user-token.md

scope 参数对应的用户信息

scope 名称对应信息
usernameusername
addressaddress
emailemail,email_verified
phonephone_number, phone_number_verified
profilebirthdate,family_name,gender,given_name,locale,middle_name,name,nickname,picture,preferred_username,profile,updated_at,website,zoneinfo
offline_access如果存在此参数,token 接口会返回 refresh_token 字段
roles对应 role 信息,用户的角色列表
unionid用户的 unionid 字段
openid用户的 openid 字段
external_id用户在原有系统的用户 ID
extended_fields用户的扩展字段信息,内容为一个对象,key 为扩展字段名,value 为扩展字段值

以上为 GenAuth 默认支持的 Scope,你也可以在应用的「协议配置」功能区中进行「自定义 OIDC Scope」的配置。

OIDC 用户信息字段含义

字段名翻译
subsubject 的缩写,唯一标识,一般为用户 ID
name姓名
given_name名字
family_name姓氏
middle_name中间名
nickname昵称
preferred_username希望被称呼的名字
profile基础资料
picture头像
website网站链接
email电子邮箱
email_verified邮箱是否被认证
gender性别
birthdate生日
zoneinfo时区
locale区域
phone_number手机号
phone_number_verified认证手机号
address地址
formatted详细地址
street_address街道地址
locality城市
region
postal_code邮编
country国家
updated_at信息更新时间

参考 OIDC 规范

IdToken 与 AccessToken 的区别

IdToken 相当于用户的身份证,开发者的前端访问后端接口时应当携带 IdToken开发者服务器应该校验用户的 IdToken,验证通过后返回相关资源,可用 OIDC 应用的密钥或 OIDC 应用公钥验签,然后可以得到此 token 对应的用户 ID 以及基本信息。示例代码请见:使用应用密钥验证 Token

AccessToken 用于请求 GenAuth 服务器上该用户持有的资源。你访问 GenAuth 服务器的请求需要在 Authorization 请求头中携带此 AccessToken,示例代码如下:

js
const axios = require("axios");
axios
  .get({
    url: "https://core.authing.cn/api/v2/your/resources",
    headers: {
      Authorization: "Bearer YOUR_OIDC_ACCESS_TOKEN",
    },
  })
  .then((res) => {
    // custom codes
  });

为什么 OIDC 授权码流程要 code 换 token 再换用户信息

OIDC 授权码模式的认证流程中涉及三方:用户、OIDC 服务器(OIDC Provider,简称 OP)、应用业务服务器(Service Provider,简称 SP)。

SP、用户、OP 的交互目的分为以下几点:

  1. SP 希望拿到一个可信的身份断言,从而让用户登录。
  2. SP 发起登录,会跳转到 OP 的认证页面,OP 让用户登录,并授权自己的信息,然后 OP 将一个授权码(code)发给 SP。实际上这是在通过引用来传递用户信息。
  3. SP 收到授权码 code 后,结合 Client ID 和 Client Secret 到 OP 换取该用户的 access_token
  4. SP 利用 access_token 到 OP 去获取用户的相关信息,从而得到一个可信的身份断言,让用户登录。

OIDC 协议中,用户登录成功后,OIDC 认证服务器会将用户的浏览器回调到一个回调地址,并携带一个授权码(code)。此授权码一般有效期十分钟且一次有效,用后作废。这避免了在前端暴露 access_token 或者用户信息的风险,access_token 的有效期都比较长,一般为 1~2 个小时。如果泄露会对用户造成一定影响。

后端收到这个 code 之后,需要使用 Client Id + Client Secret + Code 去 OIDC 认证服务器换取用户的 access_token。在这一步,实际上 OIDC Server 对 OAuth Client 进行了认证,能够确保来 OIDC 认证服务器获取 access_token 的机器是可信任的,而不是任何一个人拿到 code 之后都能来 OIDC 认证服务器进行 code 换 token。

如果 code 被黑客获取到,如果他没有 Client Id + Client Secret 也无法使用,就算有,也要和真正的应用服务器竞争,因为 code 一次有效,用后作废,加大了攻击难度。相反,如果不经过 code 直接返回 access_token 或用户信息,那么一旦泄露就会对用户造成影响。

面向 Agent 的身份、记忆与网页行动基础设施。