openid over oauth2.0 详解

默认分类,others 2021-07-31 93 次浏览 次点赞

openid over oauth2.0 详解

logo

需要在thingsboard上面加oauth server功能。

如上是一开始的需求,但是随着深入理解,这里的oauth server并不正确,所以需要先科普知识。

oauth2.0

对于oatuh ,参考oauth2.0,里framework里面并没有定义oatuh server 角色。它定义了4个角色

  • resource ower;

    资源拥有者;

  • resource server;

    资源服务器,对外提供访问接口;

  • client

    客户端,需要访问资源的对象;

  • authorization server;

    授权服务器;

提示:上下文需要反复提到 authorization 和 athentication,这里我们需要明确定义。首先看一段spring-security-architecture官方解释。

Application security boils down to two more or less independent problems: authentication (who are you?) and authorization (what are you allowed to do?). Sometimes people say “access control” instead of "authorization", which can get confusing, but it can be helpful to think of it that way because “authorization” is overloaded in other places.

这里athentication 理解为认证(我是谁?),authorization 为授权(我能干些什么?)。自然而然,这里oatuh 其实是authorization。

尽管我们还不知道明确这角色的区分,但是我们需求更接近authorization server。

接下来理解oatuh2.0 的协议流程。

+--------+                               +---------------+
|        |--(A)- Authorization Request ->|   Resource    |
|        |                               |     Owner     |
|        |<-(B)-- Authorization Grant ---|               |
|        |                               +---------------+
|        |
|        |                               +---------------+
|        |--(C)-- Authorization Grant -->| Authorization |
| Client |                               |     Server    |
|        |<-(D)----- Access Token -------|               |
|        |                               +---------------+
|        |
|        |                               +---------------+
|        |--(E)----- Access Token ------>|    Resource   |
|        |                               |     Server    |
|        |<-(F)--- Protected Resource ---|               |
+--------+                               +---------------+
提示 : 详细参考 rfc6749#section-1.2 Protocol Flow

看图理解,比较简单。

  • A 客户端发起认证请求;
  • B 资源拥有者同意访问,并且返回一个授权;
  • C 客户端通过该授权继续请求;
  • D 授权服务器分配访问访问令牌;
  • E 客户端通过令牌完成保护资源的访问;
  • F 完成保护资源的访问;

对于过程B,区分不同授权类型(Grant Type),详细参考rfc6749#section-1.3. Authorization Grant,对于oauth2.0 用以登录,也就是thingsboard 的oauth login功能,其实采用了这里的4.1. Authorization Code Grant

在该类型下,oauth login完整交互流程如下。

+----------+
| Resource |
|   Owner  |
|          |
+----------+
^
|
(B)
+----|-----+          Client Identifier      +---------------+
|         -+----(A)-- & Redirection URI ---->|               |
|  User-   |                                 | Authorization |
|  Agent  -+----(B)-- User authenticates --->|     Server    |
|          |                                 |               |
|         -+----(C)-- Authorization Code ---<|               |
+-|----|---+                                 +---------------+
|    |                                         ^      v
(A)  (C)                                        |      |
|    |                                         |      |
^    v                                         |      |
+---------+                                      |      |
|         |>---(D)-- Authorization Code ---------'      |
|  Client |          & Redirection URI                  |
|         |                                             |
|         |<---(E)----- Access Token -------------------'
+---------+       (w/ Optional Refresh Token)

这里引入User-Agent角色和(B) User authenticates流程,整个流程看起来这里更为复杂。

  • 这里的User-Agent可以理解为浏览器,对于前后端分离的应用,这里指浏览器的前端应用。这也是通过浏览器调试(F12)->网络(Network)功能并不能完整抓取如上流程完整通信。对于D、E 流程,Client到Authorization Server其实是在后台完成的。
  • 而对于User authenticates 其实是上文反复提到的授权是基于认证的,也就是他会在浏览器跳转用户认证页面。

对于如上流程,我们从本地应用和抓包的来加深理解。

spring authorization server

对于spring authorization server ,spring security 并未提供实现,spring社区提供一个测试版本,当前在0.1.2版本,该工程包含如上Client、Authorization Sever、Resouce Sever 不同角色的测试代码包含在[samples]()。

spring-authorization-server/samples/boot/oauth2-integration$ tree -L 1
.
├── authorizationserver
├── authorizationserver-custom-consent-page
├── client
├── README.adoc
└── resourceserver
对于该工程,这里不做详解,详细参考其README

成功运行该工程后直接从浏览器 网络调试功能(F12->Network)抓包。对于后台这里通过wireshark抓包。

这里直接从http请求概述交互流程。

spring 序列图

这里详细概述如上UML序列图的http请求及其参数,完整抓wireshark文件点击下载

提示:如下过程是通过浏览器调试网络(F12->Network)功能抓取
  • /oauth2/authorizition

    http://127.0.0.1:8080/oauth2/authorization/messaging-client-oidc
  • /oauth2/authorize

    http://auth-server:9000/oauth2/authorize?response_type=code&client_id=messaging-client&scope=openid&state=0AL57uKp9ITb6Z4bKSl7MXA2xiIC6hIBf_OmeS2sGSM%3D&redirect_uri=http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc&nonce=Fja1QhcE00e1jzRI_2uGKuM1XOrZjbuvAgSlQeaxIuQ
    keyvalue
    response_typecode
    client_idmessaging-client
    scopeopenid
    state0AL57uKp9ITb6Z4bKSl7MXA2xiIC6hIBf_OmeS2sGSM%3D
    redirect_urihttp://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc
    nonceFja1QhcE00e1jzRI_2uGKuM1XOrZjbuvAgSlQeaxIuQ
  • login

    http://auth-server:9000/login
  • login

    http://auth-server:9000/login
    keyname
    usernameuser1
    passwordpassword
    _csrfb994b1be-3aec-4792-9a07-ba1c7e4b12d2
  • /oauth2/authorize

    http://auth-server:9000/oauth2/authorize?response_type=code&client_id=messaging-client&scope=openid&state=0AL57uKp9ITb6Z4bKSl7MXA2xiIC6hIBf_OmeS2sGSM%3D&redirect_uri=http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc&nonce=Fja1QhcE00e1jzRI_2uGKuM1XOrZjbuvAgSlQeaxIuQ
    keyvalue
    response_typecode
    client_idmessaging-client
    scopeopenid
    state0AL57uKp9ITb6Z4bKSl7MXA2xiIC6hIBf_OmeS2sGSM%3D
    redirect_urihttp://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc
    nonceFja1QhcE00e1jzRI_2uGKuM1XOrZjbuvAgSlQeaxIuQ
  • /login/oauth2/code

    http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc?code=fKRMDYWIgkbrhoPVD-5IIMuK5opn5d1Su2d8xVCipDovbRxsRgL6x--NqG4BH30ASGtolZWToWV1XhXO8O92zz7LhLi-iszy4vJPyiS3AQ0Kmzyj7ZtRd2LEToLfwFzC&state=0AL57uKp9ITb6Z4bKSl7MXA2xiIC6hIBf_OmeS2sGSM%3D
    keyvalue
    codefKRMDYWIgkbrhoPVD-5IIMuK5opn5d1Su2d8xVCipDovbRxsRgL6x--NqG4BH30ASGtolZWToWV1XhXO8O92zz7LhLi-iszy4vJPyiS3AQ0Kmzyj7ZtRd2LEToLfwFzC
    state0AL57uKp9ITb6Z4bKSl7MXA2xiIC6hIBf_OmeS2sGSM%3D
提示: 接下来的流程通过wireshark抓取。
  • /oauth2/token

    http://auth-server:9000/oauth2/token
    keyvalue
    grant_typeauthorization_code
    codefKRMDYWIgkbrhoPVD-5IIMuK5opn5d1Su2d8xVCipDovbRxsRgL6x--NqG4BH30ASGtolZWToWV1XhXO8O92zz7LhLi-iszy4vJPyiS3AQ0Kmzyj7ZtRd2LEToLfwFzC
    redirect_urihttp://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc

    response

    keyvalue
    access_tokeneyJraWQiOiJiNDY3OTRhMy0wNDllLTRkYTYtYWIxZi1kY2IwM2E4NzM5MmMiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyMSIsImF1ZCI6Im1lc3NhZ2luZy1jbGllbnQiLCJuYmYiOjE2Mjc3MzAxNTYsInNjb3BlIjpbIm9wZW5pZCJdLCJpc3MiOiJodHR
    refresh_tokennHcV1-SEeoTfZSZlf_CLf1ag2BE36V1sahiGiFp8o0048kLR86wDN9QLCADAB2PLrneJivT4JG3lliUVP1WCHdn7ywMaAZT3eSW8fIjfNFEr95R0Rcxz3qhjybgiB3zP
    scopeopenid
    id_tokeneyJraWQiOiJiNDY3OTRhMy0wNDllLTRkYTYtYWIxZi1kY2IwM2E4NzM5MmMiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyMSIsImF1ZCI6Im1lc3NhZ2luZy1jbGllbnQiLCJhenAiOiJtZXNzYWdpbmctY2xpZW50IiwiaXNzIjoiaHR0cDpcL1wvYXV0aC1.eyJzdWIiOiJ1c2VyMSIsImF1ZCI6Im1lc3NhZ2luZy1jbGllbnQiLCJhenAiOiJtZXNzYWdpbmctY2xpZW50IiwiaXNzIjoiaHR0cDpcL1wvYXV0aC1
    token_typeBearer
    expires_in299
  • /oatuh2/jwks

    http://127.0.0.1:9000/oauth2/jwks
    keyvalue
    keys[{"kty":RSA},{"e":AQAB},]{"kid":b46794a3-049e-4da6-ab1f-dcb03a87392c},{"n":jZqBsnPZ5mbSwKsr7b6jZ3FNY0dh96ta_xyGTG0i0JrQ1UCJKoTlN_lIJ_jGu3OVeMko5K3pruyCAySm_vQa2qhUm1RDUxG_WZS9WjCo07bLb76K0u6f8e3EQVaJAnadmkpK4ijVqeBDIs0WyuvEnuh3Jk58H46tWwSEQYyVnyaLUP8aRSqh0GW3AInG-LMnJoCV6cFBIIKsKyMGdyjs}]

acess token

对于acess token,官方描述具有scope,会逾期,比较难理解。其实只需要将access token解码后就一目了然。

eyJraWQiOiJiNDY3OTRhMy0wNDllLTRkYTYtYWIxZi1kY2IwM2E4NzM5MmMiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyMSIsImF1ZCI6Im1lc3NhZ2luZy1jbGllbnQiLCJuYmYiOjE2Mjc3MzAxNTYsInNjb3BlIjpbIm9wZW5pZCJdLCJpc3MiOiJodHR
  • header

    {
      "kid": "b46794a3-049e-4da6-ab1f-dcb03a87392c",
      "typ": "JWT",
      "alg": "RS256"
    }
  • payload

    "{\"sub\":\"user1\",\"aud\":\"messaging-client\",\"nbf\":1627730156,\"scope\":[\"openid\"],\"iss\":\"htt"
  • ignature

security

这里梳理整个oauth2.0 的安全设计。

  • 首先需要说明的是整过过程可以抓包分析,是因为调试需要,我们采用的http而不是https;
  • access token 的请求和都是在后台完成,签名和验签都在authorization server自己完成,不存在公私钥泄露风险;
  • client id、secret,redirect url 预分配,需要一一对应。

openid

当我们把如上测试的authorization server用以thingsboard login的时候,出现报错,提示请求userinfo 出错。

从而引出一个新的标准 openid。不难理解如上过程oauth2.0 只是完成授权,授权后拉取用户信息,同时使用使用该用户信息在当前系统注册新用户并且跳转登录是oatuh login,都是openid完成约定的。

+--------+                                   +--------+
|        |                                   |        |
|        |---------(1) AuthN Request-------->|        |
|        |                                   |        |
|        |  +--------+                       |        |
|        |  |        |                       |        |
|        |  |  End-  |<--(2) AuthN & AuthZ-->|        |
|        |  |  User  |                       |        |
|   RP   |  |        |                       |   OP   |
|        |  +--------+                       |        |
|        |                                   |        |
|        |<--------(3) AuthN Response--------|        |
|        |                                   |        |
|        |---------(4) UserInfo Request----->|        |
|        |                                   |        |
|        |<--------(5) UserInfo Response-----|        |
|        |                                   |        |
+--------+                                   +--------+

在openid规范里,这里已经转换角色。RP作为openid 客户端,OP作为openid Provider,服务提供者。

  • (1)、(2)、(2) 已经比较熟悉了,对应oauth2.0流程A-E流程。
  • (4)、(5) 作为openid流程,也就是在oauth2.0 获取AcessToken之后主动获取用户信息。

而对于userinfo 端点点在当前的spring authorization server 还不支持,我们可以使用openid认证的开源库测试。


本文由 lijie 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处,点赞2

还不快抢沙发

添加新评论