• 【OAuth2】十九、OpenID Connect 动态客户端注册


    一、OpenID定义了客户信息注册

    参考的
    OpenID Connect 1.0 是 OAuth 2.0 协议之上的简单身份层。它使客户端能够根据授权服务器执行的身份验证验证最终用户的身份,并以可互操作和类似 REST 的方式获取有关最终​​用户的基本配置文件信息。

    该规范定义了 OpenID Connect 依赖方如何动态地向最终用户的 OpenID 提供者注册,向 OpenID 提供者提供有关自身的信息,并获取使用它所需的信息,包括此依赖方的 OAuth 2.0 客户端 ID。

    二、客户端元数据

    客户端具有与其在授权服务器上的唯一客户端标识符相关联的元数据。这些范围可以从面向人的显示字符串(例如客户端名称)到影响协议安全性的项目(例如有效重定向 URI 列表)。

    • 客户端元数据值以两种方式使用:

    作为注册请求的输入值,以及
    作为注册响应和读取响应中的输出值

    1、OpenID Connect 客户端元数据值:

    • redirect_uris
    • response_types
    • grant_types
      OpenID Connect 使用的授权类型值为:
      authorization_code:OAuth 授权代码授予类型。
      implicit:OAuth 隐式授权类型。
      refresh_token:OAuth刷新令牌授予类型。
      客户端将使用的 response_type 值和 必须包含在已注册的grant_types列表 中的grant_type值之间的对应关系:
      • code: authorization_code
    • -id_token: implicit
    • -token id_token: implicit
    • -code id_token: authorization_code, implicit
    • -code token: authorization_code, implicit
    • -code token id_token: authorization_code, implicit
    • client_name
    • tos_uri
    • policy_uri
    • logo_uri
    • client_uri
      在Spring Authorization Server中元数据在OidcClientRegistration
      在这里插入图片描述

    2、客户端注册端点/connect/registe-请求

    为了在授权服务器上注册一个新的客户端,客户端向客户端注册端点发送一条 请求路径为 /connect/registe的HTTP POST消息,其中包含客户端在注册期间选择为自己指定的任何客户端元数据参数。授权服务器为这个客户端分配一个唯一的客户端标识符,可选地分配一个客户端秘密,并将请求中给出的元数据与发出的客户端标识符相关联。授权服务器可以为客户端元数据中省略的任何项目提供默认值。就是授权服务器(OP)提供了一个资源接口,通过特定的scope的访问令牌来进行注册客户端的请求

    POST /connect/register HTTP/1.1
      Content-Type: application/json
      Accept: application/json
      Host: server.example.com
      Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJ
    
      {
       "application_type": "web",
       "redirect_uris":
         ["https://client.example.org/callback",
          "https://client.example.org/callback2"],
       "client_name": "My Example",
       "logo_uri": "https://client.example.org/logo.png",
       "subject_type": "pairwise",
       "sector_identifier_uri":
         "https://other.example.net/file_of_redirect_uris.json",
       "token_endpoint_auth_method": "client_secret_basic",
       "jwks_uri": "https://client.example.org/my_public_keys.jwks",
       "userinfo_encrypted_response_alg": "RSA1_5",
       "userinfo_encrypted_response_enc": "A128CBC-HS256",
       "contacts": ["ve7jtb@example.org", "mary@example.org"],
       "request_uris":
         ["https://client.example.org/rf.txt
           #qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA"]
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    成功注册后,客户端注册端点返回新创建的客户端标识符和(如果适用)客户端密码,以及有关此客户端的所有已注册元数据,包括授权服务器本身提供的任何字段。授权服务器可以拒绝或替换任何客户端请求的字段值,并用合适的值替换它们。如果发生这种情况,授权服务器必须在对客户端的响应中包含这些字段。授权服务器可以忽略客户端提供的值,并且必须忽略客户端发送的任何它不理解的字段。

    3、客户端注册端点/connect/registe-响应

    • client_id
      必需的。唯一的客户标识符。它目前不得对任何其他注册客户有效。
    • client_secret
      可选的。客户机密。不得将相同的客户端密钥值分配给多个客户端。机密客户端使用此值向令牌端点进行身份验证,如 OAuth 2.0 的第 2.3.1 节所述,并用于推导对称加密密钥值,如OpenID Connect Core 1.0 [OpenID.Core]的第 10.2 节所述. 除非使用对称加密 , 否则客户端不需要选择private_key_jwt的- token_endpoint_auth_method 。
    • 注册访问令牌
      可选的。注册访问令牌,可在客户端配置端点用于在客户端注册时执行后续操作。
    • 注册客户端uri
      可选的。客户端配置端点的位置,注册访问令牌可用于在生成的客户端注册后执行后续操作。实现必须要么返回客户端配置端点和注册访问令牌,要么都不返回。
    • client_id_issued_at
      可选的。发布客户端标识符的时间。它的值是一个 JSON 数字,表示从 1970-01-01T0:0:0Z 到日期/时间的秒数,以 UTC 度量。
    • client_secret_expires_at
      如果发布了client_secret,则需要。client_secret过期的时间,如果不会过期,则为 0。它的值是一个 JSON 数字,表示从 1970-01-01T0:0:0Z 到日期/时间的秒数,以 UTC 度量。
    HTTP/1.1 201 创建
      内容类型:应用程序/json
      缓存控制:无存储
      Pragma:无缓存
    
      {
       "client_id": "s6BhdRkqt3",
       “client_secret”:
         "ZJYCqe3GGRvdrudKyZS0XhGv_Z45DuKhCUk0gBR1vZk",
       “client_secret_expires_at”:1577858400,
       “registration_access_token”:
         "this.is.an.access.token.value.ffx83",
       “registration_client_uri”:
         "https://server.example.com/connect/register?client_id=s6BhdRkqt3",
       “token_endpoint_auth_method”:
         "client_secret_basic",
       “应用程序类型”:“网络”,
       “redirect_uris”:
         ["https://client.example.org/callback",
          "https://client.example.org/callback2"],
       "client_name": "我的例子",
       “client_name#ja-Jpan-JP”:
         “客户名称”,
       "logo_uri": "https://client.example.org/logo.png",
       “subject_type”:“成对”,
       “sector_identifier_uri”:
         "https://other.example.net/file_of_redirect_uris.json",
       "jwks_uri": "https://client.example.org/my_public_keys.jwks",
       “userinfo_encrypted_response_alg”:“RSA1_5”,
       "userinfo_encrypted_response_enc": "A128CBC-HS256",
       “联系人”:[“ve7jtb@example.org”,“mary@example.org],
       “request_uris”:
         ["https://client.example.org/rf.txt
           #qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA”]
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    3、根据client_id读取 客户端注册端点

    如果客户端的初始注册返回了客户端配置端点和注册访问令牌,则可以通过使用注册访问令牌向客户端配置端点发出 HTTP GET请求来 读取授权服务器上客户端的当前配置。

    GET /connect/register?client_id=s6BhdRkqt3 HTTP/1.1
      Accept: application/json
      Host: server.example.com
      Authorization: Bearer this.is.an.access.token.value.ffx83
    
    • 1
    • 2
    • 3
    • 4

    4、小结

    OIDC定义了有限对外开放的客户端注册端点,这个端点在做开放平台的时候非常有用。

    三 、Spring Authorization Server中如何实现这一功能。

    在这里插入图片描述

    • 上面代码中的OidcClientRegistrationEndpointConfigurer 并不是直接初始化的,也就是说OidcClientRegistrationEndpointFilter框架并没有设置
    • 这时就需要我们进行设置了。
    OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer =
                        new OAuth2AuthorizationServerConfigurer<>();
    authorizationServerConfigurer.oidc(oidcConfigurer ->
                       oidcConfigurer.clientRegistrationEndpoint(Customizer.withDefaults()));
    
    • 1
    • 2
    • 3
    • 4

    1、OidcClientRegistrationEndpointFilter

    在这里插入图片描述
    OidcClientRegistrationEndpointFilter 拦截的请求为/connect/register
    在这里插入图片描述

    2、OidcClientRegistrationAuthenticationProvider

    OidcClientRegistrationAuthenticationToken交给OidcClientRegistrationAuthenticationProvider后,首先提取access_token,查询校验access_token。

    然后查看OidcClientRegistrationAuthenticationToken是否封装了OidcClientRegistration,如果封装了就是新增或者更新;没有就是查询。
    在这里插入图片描述

    • 一般注册和更新客户端信息是POST请求,查询是GET请求。
    • GET请求,请求参数中需要携带client_id。
    • 如果是POST请求,需要access_token需要client.write的scope,并且该access_token只能使用一次,注册客户端成功后会销毁该access_token,同时新生成一个包含client.read的access_token供GET请求查询使用。
    • client_secret_basic模式下,客户端的client_secret是被PasswordEncoder摘要过的密文,而这里并没有具体的实现。这就要求实现RegisteredClientRepository的时候加入相关的PasswordEncoder逻辑

    四 、OpenID 提供的元信息

    参考

    1、OpenID 提供者配置请求

    使用 HTTP GET请求来查询 OpenID 提供者配置文档。

    OP 将向 Issuer https://example.com发出以下请求以 获取其配置信息,因为 Issuer 不包含路径组件

      GET /.well-known/openid-configuration HTTP/1.1
      Host: example.com
    
    • 1
    • 2

    响应是一组关于 OpenID 提供者配置的声明,包括所有必要的端点和公钥位置信息。

    2、OidcProviderConfigurationEndpointFilter

    提供者响应数的数据是有该过滤器处理的
    在这里插入图片描述

  • 相关阅读:
    计算机中整数的加减运算
    【Git】IDEA中Git常用的终端操作
    R语言使用使用as_tibble函数和names函数基于一个dataframe的列名列表创建一个新的dataframe
    湖南省副省长秦国文一行调研考察亚信科技
    【Java从入门到精通 05】:Java中的程序控制结构和数组
    常见的加解密及编码总结
    什么是畏缩型性格?如何改变畏缩型性格?
    DC/DC开关电源学习笔记(八)DC/DC功率变换的研究内容
    国内首发可视化智能调优平台,小龙带你玩转KeenTune UI
    List集合之UML、特点、遍历方式、迭代器原理、泛型、装拆箱及ArrayList、LinkedList和Vector的区别
  • 原文地址:https://blog.csdn.net/weixin_43333483/article/details/126236208