前面的博文中反复提及一些对接 OIDC 服务的身份认证平台的具体案例,它们在工作中可能会非常频繁地使用到,因为身份认证是一个非常基础的功能,几乎所有的应用都需要。今天在这里来做个回顾总结,对它们的一般步骤进行一个统一梳理。

(1)在身份认证平台注册应用

首先,我们需要在身份认证平台注册应用,这是接入身份认证的第一步。在注册应用时,我们需要提供应用的基本信息,例如应用名称、应用图标、应用描述等。但是,最重要的是我们需要提供应用的回调地址,这是身份认证平台用来将用户重定向回应用的地址。当然,我们还需要给应用起个名字,这个名字在身份认证平台中被称为客户端 ID。

表:注册应用时需要提供的信息

信息 说明
㊔ 应用名称 应用的名称,用来标识一个客户端
🔙 重定向地址 您的应用端点将在用户被授权后从身份认证平台接收一些安全信息。

(2)在应用中配置身份认证平台的信息

一般的 OIDC 客户端都会默认从 OIDC 服务器的 /.well-known/openid-configuration 端点获取 OIDC 服务器的配置信息,这个端点是 OIDC 协议规定的,所有的 OIDC 服务器都必须实现。在这个端点中,OIDC 服务器会返回一些重要的信息,例如 OIDC 服务器的地址、支持的 OIDC 协议版本、支持的 OIDC 授权类型、支持的 OIDC Response Type、支持的 OIDC Scope、支持的 OIDC 签名算法、支持的 OIDC JWK 签名密钥等等。OIDC 客户端会根据这些信息来配置自己的 OIDC 客户端,以便与 OIDC 服务器进行交互。
如果您的 OIDC 客户端不支持从 /.well-known/openid-configuration 端点获取 OIDC 服务器的配置信息,那么您可以手动配置 OIDC 客户端,将 OIDC 服务器的地址、支持的 OIDC 协议版本、支持的 OIDC 授权类型、支持的 OIDC Response Type、支持的 OIDC Scope、支持的 OIDC 签名算法、支持的 OIDC JWK 签名密钥等信息填写到 OIDC 客户端中。

(3)构造 OIDC 授权请求

在 OIDC 协议中,OIDC 授权请求是 OIDC 客户端向 OIDC 服务器发起的第一个请求,用于请求 OIDC 服务器对用户进行身份认证和授权。OIDC 授权请求中包含了 OIDC 客户端的身份信息,以及 OIDC 客户端请求的 OIDC 授权类型、OIDC Response Type、OIDC Scope、OIDC 随机数、OIDC 重定向地址等信息。
这个请求地址可以从 OIDC 服务器的 /.well-known/openid-configuration 端点中获取,一般是 https://oidc-server.com/connect/authorize 。如下图所示:
image.png
一个授权请求的 URL 示例如下:

https://oidc-server.com/connect/authorize? client_id=client_id& response_type=code& scope=openid%20profile& redirect_uri=https%3A%2F%2Fclient.com%2Fcallback& state=state&

这时浏览器就会被重定向至身份认证平台的域,而身份认证平台最终会展示一个登录页面,让用户输入用户名和密码(或者其他凭据)进行登录。登录成功后,身份认证平台会将用户重定向回应用的回调地址,并在 URL 中带上授权码和状态码,如:

https://client.com/callback? code=code& state=state

(4)构造 OIDC Token 请求

在上面的一步中,你的应用已经接收到了来自 OIDC 服务器的授权码,接下来你的应用需要使用这个授权码来向 OIDC 服务器请求 OIDC Token。OIDC Token 请求是 OIDC 客户端向 OIDC 服务器发起的第二个请求,用于请求 OIDC 服务器颁发 OIDC Token。OIDC Token 请求中包含了 OIDC 客户端的身份信息,以及 OIDC 客户端请求的 OIDC Token 类型、OIDC 授权码、OIDC 重定向地址等信息。
这个请求地址可以从 OIDC 服务器的 /.well-known/openid-configuration 端点中获取,一般是 https://oidc-server.com/connect/token 。如下图所示:
image.png
一个 OIDC Token 请求的 URL 示例如下: latex https://oidc-server.com/connect/token? client_id=client_id& client_secret=client_secret& grant_type=authorization_code& code=code& redirect_uri=https%3A%2F%2Fclient.com%2Fcallback

这个请求可以使用 HTTP GET 或者 HTTP POST 方法发送,但是一般情况下,我们会使用 HTTP POST 方法发送这个请求,因为这个请求中包含了客户端的机密信息,例如客户端的密钥,如果使用 HTTP GET 方法发送这个请求,那么这些机密信息会暴露在 URL 中,这是非常危险的。

以上请求得到的成功响应往往是类似下面这样的格式:

json { id_token: eyJhbGciOi..., access_token: eyJhbGciOi..., expires_in: 1800, token_type: Bearer, refresh_token: D8C63836215563320F809E29EB57D1B23DD3792722C6DFE07B99199E154B4412-1, scope: openid email profile offline_access }

(5)使用 OIDC Token 请求 OIDC 用户信息

在上一步中,我们已经成功地从 OIDC 服务器获取到了 OIDC Token,接下来我们需要使用这个 OIDC Token 来请求 OIDC 用户信息。OIDC 用户信息请求是 OIDC 客户端向 OIDC 服务器发起的第三个请求,用于请求 OIDC 服务器返回 OIDC 用户信息。OIDC 用户信息请求中包含了 OIDC 客户端的身份信息,以及 OIDC 客户端请求的 OIDC Token、OIDC 用户信息等信息。

这个请求地址可以从 OIDC 服务器的 /.well-known/openid-configuration 端点中获取,一般是 https://oidc-server.com/connect/userinfo 。如下图所示:
image.png
![OIDC 用户信息请求](../resources/oidc-userinfo.png#id=z4Stj&originalType=binary∶=1&rotation=0&showTitle=true&status=done&style=none&title=OIDC%20%E7%94%A8%E6%88%B7%E4%BF%A1%E6%81%AF%E8%AF%B7%E6%B1%82 OIDC 用户信息请求)

一个 OIDC 用户信息请求的 URL 示例如下:

latex https://oidc-server.com/connect/userinfo? access_token=access_token

这个请求可以使用 HTTP GET 或者 HTTP POST 方法发送,但是一般情况下,我们会使用 HTTP GET 方法发送这个请求,因为这个请求中不包含任何机密信息。

以上请求得到的成功响应往往是类似下面这样的格式:

json { sub: d9df1959-7a18-4753-8642-c0ec0d20ae67, email: jeff.tian@outlook.com, preferred_username: jeff-tian, name: jeff, email_verified: true }

(6)调用退出端点

当您想要登出用户时,您需要将用户重定向到身份认证平台的结束会话端点,同时带有从令牌端点获取的id_token以及应用程序的URL。例如:

latex https://oidc-server.com/connect/endsession?id_token_hint=${id_token}&post_logout_redirect_uri=${encodeURIComponent(应用地址)}

具体的退出登录端点地址可以从 OIDC 服务器的 /.well-known/openid-configuration 端点中获取,一般是 https://oidc-server.com/connect/endsession 。如下图所示:
image.png
![OIDC 退出端点](../resources/oidc-logout.png#id=TNBcw&originalType=binary∶=1&rotation=0&showTitle=true&status=done&style=none&title=OIDC%20%E9%80%80%E5%87%BA%E7%AB%AF%E7%82%B9 OIDC 退出端点)

一个典型的退出时序图如下图所示:

相关故障排除指引

这里列出一些常常遇到的问题,以及解决方案:

为什么无法从用户信息接口里获取到 Email

检查在构造授权请求的环节,传递给授权端点的范围(scope)。如果没有请求电子邮件(email),那么它就不会返回。典型的范围是 openid profile email。

为什么无法退出

检查您的应用程序是否正确配置,特别是关于结束会话端点的部分。否则,很可能只是假地重定向到了一个退出登录的页面而已,一旦点击重新登录,都不需要输入用户凭据,就直接进入了登录态。

总结

本文总结了接入 OIDC 服务的一般步骤,具体如下:

  1. 在身份认证平台注册应用:提供应用基本信息和回调地址。
  2. 在应用中配置身份认证平台信息:默认从 OIDC 服务器的 /.well-known/openid-configuration 获取配置信息,或手动配置 OIDC 客户端。
  3. 构造 OIDC 授权请求:包括客户端身份信息、授权类型、响应类型等,重定向至身份认证平台进行用户登录验证。
  4. 构造 OIDC Token 请求:使用授权码向 OIDC 服务器请求 OIDC Token,包括身份信息、授权码等。
  5. 使用 OIDC Token 请求 OIDC 用户信息:使用 OIDC Token 向 OIDC 服务器请求用户信息,包括用户ID、邮箱、用户名等。
  6. 调用退出端点:当需要退出用户时,重定向至 OIDC 服务器的结束会话端点,并传递 id_token 和应用回调地址。

文章还提供了一些常见故障排除指引,例如无法获取邮箱信息或退出登录问题。