程序园OAuth2

基于OAuth2的OIDC (OpenId Connect) 身

2019-11-08  本文已影响0人  赵阳_c149

OIDC协议

OIDC(OpenID Connect)是在OAuth2上构建了一个身份层,是一个基于OAuth2协议的身份认证标准协议。

OAuth2协议

OAuth2是一个授权协议,它无法提供完善的身份认证功能【1】,OIDC使用OAuth2的授权服务器来为第三方客户端提供用户的身份认证,并把对应的身份认证信息传递给客户端。

使用OAuth2进行认证的常见误区

如果用OAuth2进行认证,会有许多问题。

OIDC核心概念:ID Token

OAuth2提供了Access Token来解决授权第三方客户端访问受保护资源的问题;OIDC在这个基础上提供了ID Token来解决第三方客户端标识用户身份认证的问题。OIDC的核心在于在OAuth2的授权流程中,一并提供用户的身份认证信息(ID Token)给到第三方客户端ID Token使用JWT格式来包装。此外还提供了UserInfo的接口,用户获取用户的更完整的信息。

参与角色

主要的术语以及概念介绍:

工作流程

OIDC的流程由以下5个步骤构成:

  1. RP发送一个认证请求给OP
  2. OPEU进行身份认证,然后提供授权;
  3. OPID TokenAccess Token(需要的话)返回给RP
  4. RP使用Access Token发送一个请求UserInfo EndPoint
  5. UserInfo EndPoint返回EUClaims
    oidc.jpg
    注意这里面RP发往OP的请求,是属于Authentication类型的请求,虽然在OIDC中是复用OAuth2的Authorization请求通道,但是用途是不一样的,且OIDC的AuthN请求中scope参数必须要有一个值为的openid的参数,用来区分这是一个OIDC的Authentication请求,而不是OAuth2的Authorization请求。

什么是ID Token

OIDC对OAuth2最主要的扩展就是提供了ID TokenID Token是一个安全令牌,是一个授权服务器提供的包含用户信息(由一组Cliams构成以及其他辅助的Cliams)的JWT格式的数据结构。
另外ID Token必须使用JWS进行签名和JWE加密,从而提供认证的完整性、不可否认性以及可选的保密性。一个ID Token的例子如下:

 1 {
 2    "iss": "https://server.example.com",
 3    "sub": "24400320",
 4    "aud": "s6BhdRkqt3",
 5    "nonce": "n-0S6_WzA2Mj",
 6    "exp": 1311281970,
 7    "iat": 1311280970,
 8    "auth_time": 1311280969,
 9    "acr": "urn:mace:incommon:iap:silver"
10   }

如何获取ID Token

因为OIDC基于OAuth2,所以OIDC的认证流程主要是由OAuth2的几种授权流程延伸而来的,有以下3种:

  1. Authorization Code Flow:使用OAuth2的授权码来换取Id TokenAccess Token
  2. Implicit Flow:使用OAuth2的Implicit流程获取Id TokenAccess Token
  3. Hybrid Flow:混合Authorization Code Flow+Implici Flow。

Resource Owner Password Credentials Grant是需要用途提供账号密码给RP的,账号密码给到RP了,就不再需要ID Token了。

Client Credentials Grant这种方式根本就不需要用户参与,更谈不上用户身份认证了。这也能反映授权和认证的差异,以及只使用OAuth2来做身份认证的事情是远远不够的,也是不合适的。

这里主要介绍基于Authorization Code的认证请求/答复。

基于Authorization Code的认证请求的请求

所有的Token都是通过Token EndPoint来发放的。构建一个OIDC的Authentication Request需要提供如下的参数:

以上这5个参数是和OAuth2相同的。除此之外,还定义了一些参数【2】例如:

一个简单的示例如下:

GET /authorize?
    response_type=code
    &scope=openid%20profile%20email
    &client_id=s6BhdRkqt3
    &state=af0ifjsldkj
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
  Host: server.example.com
基于Authorization Code的认证请求的响应

授权服务器接收到认证请求之后,需要对请求参数做严格的验证。验证通过后引导EU进行身份认证并且同意授权。在这一切都完成后,会重定向到RP指定的回调地址,并且把codestate参数传递过去。比如:

  HTTP/1.1 302 Found
  Location: https://client.example.org/cb?
    code=SplxlOBeZQQYbYS6WxSbIA
    &state=af0ifjsldkj
获取ID Token

RP使用上一步获得的code来请求Token EndPoint,这一步同OAuth2。然后Token EndPoint会返回响应的Token,其中除了OAuth2规定的部分数据外,还会附加一个id_token的字段。id_token字段就是上面提到的ID Token。例如:

  HTTP/1.1 200 OK
  Content-Type: application/json
  Cache-Control: no-store
  Pragma: no-cache

  {
   "access_token": "SlAV32hkKG",
   "token_type": "Bearer",
   "refresh_token": "8xLOxBtZp8",
   "expires_in": 3600,
   "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc
     yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5
     NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ
     fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz
     AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q
     Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ
     NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd
     QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS
     K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4
     XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg"
  }

其中看起来一堆乱码的部分就是JWT格式的ID Token。在RP拿到这些信息之后,需要对id_token以及access_token进行验证。至此,可以说用户身份认证就可以完成了,后续可以根据UserInfo EndPoint获取更完整的信息。

OIDC协议簇

除了Core核心规范内容多一点之外,另外7个都是很简单且简短的规范,另外Core是基于OAuth2的,也就是说其中很多东西在复用OAuth2。


oicd_p_s.png

OpenId Connect定义了一个发现协议,它允许Client轻松的获取有关如何和特定的身份认证提供者进行交互的信息。在另一方面,还定义了一个Client注册协议,允许Client引入新的身份提供程序(identity providers)。通过这两种机制和一个通用的身份API,OpenId Connect可以运行在互联网规模上运行良好,在那里没有任何一方事先知道对方的存在。

UserInfo Endpoint

UserIndo EndPoint是一个受OAuth2保护的资源。在RP得到Access Token后可以请求此资源,然后获得一组EU相关的Claims,这些信息可以说是ID Token的扩展,

  GET /userinfo HTTP/1.1
  Host: server.example.com
  Authorization: Bearer SlAV32hkKG

成功之后相应如下:

  HTTP/1.1 200 OK
  Content-Type: application/json

  {
   "sub": "248289761001",
   "name": "Jane Doe",
   "given_name": "Jane",
   "family_name": "Doe",
   "preferred_username": "j.doe",
   "email": "janedoe@example.com",
   "picture": "http://example.com/janedoe/me.jpg"
  }

【1】OAuth2中的access_token
【2】[认证 & 授权] 4. OIDC(OpenId Connect)身份认证(核心部分)

上一篇下一篇

猜你喜欢

热点阅读