前言

  上一篇文章介绍了OAuth2.0协议的相关内容,知道OAuth2.0是一个授权协议,无法提供完善的身份认证功能。那么什么来解决身份认证功能呢?——OIDC是一个不错的解决方案。接下来进一步来了解OIDC是什么,有什么效果呢?

一、OIDC是什么

  OIDC是OpenID Connect 的简称,以下是OIDC官方的描述内容:

OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.

OpenID Connect allows clients of all types, including Web-based, mobile, and JavaScript clients, to request and receive information about authenticated sessions and end-users. The specification suite is extensible, allowing participants to use optional features such as encryption of identity data, discovery of OpenID Providers, and session management, when it makes sense for them.

  主要内容:OIDC是基于OAuth2.0协议的身份层,允许客户端基于授权服务器执行的身份验证来验证最终用户的身份,并以可互操作且类似于REST的方式获取有关最终​​用户的基本配置文件信息。并且支持所有客户端类型(如基于Web的客户端,移动客户端和JavaScript客户端)请求并接收有关经过身份验证的会话和最终用户的信息

二、OIDC相关的协议

  OIDC本身是有多个规范构成,其中最主要的是一个核心的规范,多个可选支持的规范来提供扩展支持

   主要包含:

   Core:必选。定义OIDC的核心功能,在OAuth 2.0之上构建身份认证,以及如何使用Claims来传递用户的信息。
   Discovery:可选。发现服务,使客户端可以动态的获取OIDC服务相关的元数据描述信息
   Dynamic Client Registration:可选。动态注册服务,使客户端可以动态的注册到OIDC的OP
   Session Management:可选。Session管理,用于规范OIDC服务如何管理Session信息
   Form Post Response Mode:可选。针对OAuth2的扩展,OAuth2回传信息给客户端是通过URL的querystring和fragment这两种方式,这个扩展标准提供了一基于form表单的形式把数据post给客户端的机制。
   基础协议:
    OAuth2.0 Core:https://tools.ietf.org/html/rfc6749
    OAuth2.0 Bearer:https://tools.ietf.org/html/rfc6750
    OAuth2.0 Assertions:https://tools.ietf.org/html/rfc7521
    OAuth2.0 JWT Profile:https://tools.ietf.org/html/rfc7523
    OAuth2.0 Responses:可选。针对OAuth2的扩展,提供几个新的response_type。
    JWT(JSON Web Token):https://tools.ietf.org/html/rfc7519
    JWS(JSON Web Signature):https://tools.ietf.org/html/rfc7515
    JWE(JSON Web Encryption):https://tools.ietf.org/html/rfc7516    JWK(JSON Web Key):https://tools.ietf.org/html/rfc7517    JWA(JSON Web Algorithms):https://tools.ietf.org/html/rfc7518    WebFinger:https://tools.ietf.org/html/rfc7033

  

  上图是官方给出的一个OIDC组成结构图,可以看出OIDC不是什么新技术,它主要是借鉴OpenId的身份标识,OAuth2的授权和JWT包装数据的方式,组合使用这些技术就是现在的OIDC。

  接下来就来学习里面最核心的相关内容(Core核心规范)。

三、OIDC核心规范

  1、主要术语

    主要的术语以及概念介绍

    • EU:End User:最终用户。
    • RP:Relying Party ,用来代指OAuth2中的受信任的客户端,身份认证和授权信息的消费方;
    • OP:OpenID Provider,有能力提供EU认证的服务(比如OAuth2中的授权服务),用来为RP提供EU的身份认证信息;
    • ID Token:JWT格式的数据,包含EU身份认证的信息。
    • UserInfo Endpoint:用户信息接口(受OAuth2保护),当RP使用Access Token访问时,返回授权用户的信息,此接口必须使用HTTPS。

  2、主要流程

    抽象的看主要包含以下步骤:

    1. RP(客户端)将请求发送到OpenID提供程序(OP)。
    2. OP验证最终用户并获得授权。
    3. OP用ID Token(通常是访问令牌)进行响应。
    4. RP可以将带有访问令牌(Access Token)的请求发送到UserInfo EndPoint。
    5. UserInfo端点返回有关最终用户(EU)的声明(Claims)。

    

   上图取自Core规范文档,其中AuthN=Authentication,表示认证;AuthZ=Authorization,代表授权。注意这里面RP发往OP的请求,是属于Authentication类型的请求,虽然在OIDC中是复用OAuth2的Authorization请求通道,但是用途是不一样的,且OIDC的AuthN请求中scope参数必须要有一个值为的openid的参数(后面会详细介绍AuthN请求所需的参数),用来区分这是一个OIDC的Authentication请求,而不是OAuth2的Authorization请求。

  3、ID Token

    ID Token是OpenID Connect对OAuth 2.0进行的主要扩展(用于使最终用户能够通过身份验证),ID Token是一种安全令牌,其中包含有关使用客户端时授权服务器对最终用户的身份验证的声明(Claims)以及可能的其他请求的声明(Claims)的JWT格式数据。

    ID Token的主要构成部分如下:

    

名称 完整名称 是否必须 描述
iss Issuer Identifier 提供认证信息者的唯一标识。一般是一个https的url(不包含querystring和fragment部分)
sub Subject Identifier iss提供的EU的标识,在iss范围内唯一。它会被RP用来标识唯一的用户。最长为255个ASCII个字符。
aud Audience(s) 标识ID Token的受众。必须包含OAuth2的client_id
exp Expiration time 过期时间,超过此时间的ID Token会作废不再被验证通过。
iat Issued At Time JWT的构建的时间
nonce   RP发送请求的时候提供的随机字符串,用来减缓重放攻击,也可以来关联ID Token和RP本身的Session信息。
auth_time AuthenticationTime / EU完成认证的时间。如果RP发送AuthN请求的时候携带max_age的参数,则此Claim是必须的
acr Authentication Context Class Reference 表示一个认证上下文引用值,可以用来标识认证上下文类
amr Authentication Methods References 表示一组认证方法
azp  Authorized party 结合aud使用。只有在被认证的一方和受众(aud)不一致时才使用此值,一般情况下很少使用

   一般情况在ID Token中还会包含其他声明(Claims)内容,如用户姓名、头像等信息。OIDC提供了一组公共的cliams,可以到这里查看。另外ID Token必须使用JWS进行签名和JWE加密,从而提供认证的完整性、不可否认性以及可选的保密性。

   例如:

  {
"iss": "https://server.example.com",
"sub": "",
"aud": "s6BhdRkqt3",
"nonce": "n-0S6_WzA2Mj",
"exp": ,
"iat": ,
"auth_time": ,
"acr": "urn:mace:incommon:iap:silver"
}

  4、认证

   了解了ID Token后,接下来就来看OIDC如何获取ID Token的,由于OIDC基于OAuth2,所以OIDC的认证流程主要是由OAuth2的几种授权流程延伸而来的,

   有以下3种

    • Authorization Code Flow:使用OAuth2的授权码来换取Id Token和Access Token。
    • Implicit Flow:使用OAuth2的Implicit流程获取Id Token和Access Token。
    • Hybrid Flow:混合Authorization Code Flow+Implici Flow。

OAuth2中还有基于Resource Owner Password Credentials Grant和Client Credentials Grant的方式来获取Access Token,为什么OIDC没有扩展这些方式呢?

Resource Owner Password Credentials Grant是需要用户提供账号密码给RP的,账号密码给到RP,还需要什么ID Token

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

  4.1 授权码流程(Authorization Code Flow)

授权码流程执行以下步骤。

    1. 客户端准备一个包含所需请求参数的身份验证请求。
    2. 客户端将请求发送到授权服务器。
    3. 授权服务器对最终用户进行身份验证。
    4. 授权服务器获得最终用户同意/授权。
    5. 授权服务器使用授权码将最终用户发送回客户端。
    6. 客户端使用令牌端点上的授权码来请求响应。
    7. 客户端收到响应,该响应在响应主体中包含ID令牌和访问令牌。
    8. 客户端验证ID令牌并检索最终用户的主题标识符。

    4.1.1 认证请求

      该方式使用OAuth2的Authorization Code的方式来完成用户身份认证,所有的Token都是通过Token EndPoint来发放的。构建一个OIDC的Authentication Request需要提供如下的参数:

参数 必须 说明
scope OIDC的请求必须包含值为“openid”的scope的参数
response_type 同OAuth2
client_id 同OAuth2
redirect_uri 同OAuth2
state 推荐 同OAuth2,防止CSRF, XSRF
response_mode OIDC新定义的参数(OAuth 2.0 Form Post Response Mode),用来指定Authorization Endpoint以何种方式返回数据
nonce ID Token中的出现的nonce就是来源于此
display 指示授权服务器呈现怎样的界面给EU。有效值有(page,popup,touch,wap),其中默认是page。page=普通的页面,popup=弹出框,touch=支持触控的页面,wap=移动端页面。
prompt 这个参数允许传递多个值,使用空格分隔。用来指示授权服务器是否引导EU重新认证和同意授权(consent,就是EU完成身份认证后的确认同意授权的页面)。有效值有(none,login,consent,select_account)。none=不实现现任何认证和确认同意授权的页面,如果没有认证授权过,则返回错误login_required或interaction_required。login=重新引导EU进行身份认证,即使已经登录。consent=重新引导EU确认同意授权。select_account=假如EU在授权服务器有多个账号的话,允许EU选择一个账号进行认证。
max_age 代表EU认证信息的有效时间,对应ID Token中auth_time的claim。比如设定是20分钟,则超过了时间,则需要引导EU重新认证
ui_locales 用户界面的本地化语言设置项
id_token_hint 之前发放的ID Token,如果ID Token经过验证且是有效的,则需要返回一个正常的响应;如果有误,则返回对应的错误提示
login_hint 向授权服务器提示登录标识符,EU可能会使用它登录(如果需要的话)。比如指定使用用户使用blackheart账号登录,当然EU也可以使用其他账号登录,这只是类似html中input元素的placeholder。
acr_values Authentication Context Class Reference values,对应ID Token中的acr的Claim。此参数允许多个值出现,使用空格分割

      以上是基于Authorization Code方式的OIDC的认证请求所需的参数。在OIDC的其他认证流程中也会有其他的参数或不同的参数值(稍有差异)示例如下:

  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

   4.1.2 认证请求的响应

      授权服务器接收到请求后,进行了:OAuth2.0参数验证、scope参数是否包含openid的范围值、授权服务器必须参数是否存等相关验证(详见);验证通过后引导EU进行身份认证并同意授权。然后会重定向到RP指定的回调地址,并且把code和state参数传递过去:如下:

 HTTP/1.1  Found
Location: https://client.example.org/cb?
code=SplxlOBeZQQYbYS6WxSbIA
&state=af0ifjsldkj

     4.1.3 获取IDToken

      接下来PR会根据获取的Code来请求Token EndPoint,和OAuth2.0请求相同;Token EndPoint接收到请求后会返回相应的Token,除了OAuth2规定的部分数据外,还会附加一个id_token的字段。id_token字段就是上面提到的ID Token。示例如下:

  HTTP/1.1  OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache {
"access_token": "SlAV32hkKG",
"token_type": "Bearer",
"refresh_token": "8xLOxBtZp8",
"expires_in": ,
"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"
}

  4.2 隐式流(Implicit Flow)

隐式流遵循以下步骤:

    1. 客户端准备一个包含所需请求参数的身份验证请求。
    2. 客户端将请求发送到授权服务器。
    3. 授权服务器对最终用户进行身份验证。
    4. 授权服务器获得最终用户同意/授权。
    5. 授权服务器使用ID令牌和访问令牌(如果要求)将最终用户发送回客户端。
    6. 客户端验证ID令牌并检索最终用户的主题标识符。   

   4.2.1 认证请求

     按照4.1.1定义进行身份验证请求,不同的是,这些身份验证请求参数的使用方式如下:

    • response_type值换成:id_token token 或 id_token

     示例如下:      

  GET /authorize?
response_type=id_token%20token
&client_id=s6BhdRkqt3
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&scope=openid%20profile
&state=af0ifjsldkj
&nonce=n-0S6_WzA2Mj HTTP/1.1
Host: server.example.com

   4.2.1 认证请求响应

     响应结果如下:

  HTTP/1.1  Found
Location: https://client.example.org/cb#
access_token=SlAV32hkKG
&token_type=bearer
&id_token=eyJ0 ... NiJ9.eyJ1c ... I6IjIifX0.DeWt4Qu ... ZXso
&expires_in=
&state=af0ifjsldkj

  4.3 混合流(Hybrid Flow)

混合流遵循以下步骤:

    1. 客户端准备一个包含所需请求参数的身份验证请求。
    2. 客户端将请求发送到授权服务器。
    3. 授权服务器对最终用户进行身份验证。
    4. 授权服务器获得最终用户同意/授权。
    5. 授权服务器使用授权码以及一个或多个其他参数(根据响应类型)将最终用户发送回客户端。
    6. 客户端使用令牌端点上的授权码来请求响应。
    7. 客户端收到响应,该响应在响应主体中包含ID令牌和访问令牌。
    8. 客户端验证ID令牌并检索最终用户的主题标识符。

   4.3.1 认证请求

     按照4.1.1定义进行身份验证请求,不同的是,这些身份验证请求参数的使用方式如下:

    • response_type值换成:code id_tokencode token, or code id_token token.
  GET /authorize?
response_type=code%20id_token
&client_id=s6BhdRkqt3
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&scope=openid%20profile%20email
&nonce=n-0S6_WzA2Mj
&state=af0ifjsldkj HTTP/1.1
Host: server.example.com

   4.3.1 认证请求响应

    以下是使用“混合流”成功响应

  HTTP/1.1  Found
Location: https://client.example.org/cb#
code=SplxlOBeZQQYbYS6WxSbIA
&id_token=eyJ0 ... NiJ9.eyJ1c ... I6IjIifX0.DeWt4Qu ... ZXso
&state=af0ifjsldkj

总结:

   OIDC的好处:

    • OIDC使得身份认证可以作为一个服务存在

    • OIDC可以很方便的实现SSO(跨顶级域)

    • OIDC兼容OAuth2,可以使用Access Token控制受保护的API资源
    • OIDC可以兼容众多的IDP(身份提供商)作为OIDC的OP来使用

    • OIDC的一些敏感接口均强制要求TLS,除此之外,得益于JWT,JWS,JWE家族的安全机制,使得一些敏感信息可以进行数字签名、加密和验证,进一步确保整个认证过程中的安全保障

参考

官方资料:

http://openid.net/connect/

http://openid.net/connect/faq/

http://openid.net/developers/certified/

案例:https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-openid-connect-code

   

认证授权:学习OIDC的更多相关文章

  1. [认证授权] 5.OIDC(OpenId Connect)身份认证授权(扩展部分)

    在上一篇[认证授权] 4.OIDC(OpenId Connect)身份认证授权(核心部分)中解释了OIDC的核心部分的功能,即OIDC如何提供id token来用于认证.由于OIDC是一个协议族,如果 ...

  2. [认证授权] 5.OIDC(OpenId Connect)身份认证(扩展部分)

    在上一篇[认证授权] 4.OIDC(OpenId Connect)身份认证(核心部分)中解释了OIDC的核心部分的功能,即OIDC如何提供id token来用于认证.由于OIDC是一个协议族,如果只是 ...

  3. [认证授权] 4.OIDC(OpenId Connect)身份认证授权(核心部分)

    0 目录 认证授权系列:http://www.cnblogs.com/linianhui/category/929878.html 1 什么是OIDC? 看一下官方的介绍(http://openid. ...

  4. [认证授权] 4.OIDC(OpenId Connect)身份认证(核心部分)

    1 什么是OIDC? 看一下官方的介绍(http://openid.net/connect/): OpenID Connect 1.0 is a simple identity layer on to ...

  5. 认证授权-学习笔记2-OpenId Connect

    简介 简单来说:OIDC是OpenID Connect的简称,OIDC=(Identity, Authentication) + OAuth 2.0.它在OAuth2上构建了一个身份层,是一个基于OA ...

  6. Spring security OAuth2.0认证授权学习第三天(认证流程)

    本来之前打算把第三天写基于Session认证授权的,但是后来视屏看完后感觉意义不大,而且内容简单,就不单独写成文章了; 简单说一下吧,就是通过Servlet的SessionApi 通过实现拦截器的前置 ...

  7. Spring security OAuth2.0认证授权学习第一天(基础概念-认证授权会话)

    这段时间没有学习,可能是因为最近工作比较忙,每天回来都晚上11点多了,但是还是要学习的,进过和我的领导确认,在当前公司的技术架构方面,将持续使用Spring security,暂不做Shiro的考虑, ...

  8. 认证授权-学习笔记1-OAuth 2.0

    简介 客户端必须得到用户的授权(authorization grant),才能获得令牌(access token).OAuth 2.0定义了四种授权方式. 授权码模式(authorization co ...

  9. Spring security OAuth2.0认证授权学习第四天(SpringBoot集成)

    基础的授权其实只有两行代码就不单独写一个篇章了; 这两行就是上一章demo的权限判断; 集成SpringBoot SpringBoot介绍 这个篇章主要是讲SpringSecurity的,Spring ...

  10. Spring security OAuth2.0认证授权学习第二天(基础概念-授权的数据模型)

    如何进行授权即如何对用户访问资源进行控制,首先需要学习授权相关的数据模型. 授权可简单理解为Who对What(which)进行How操作,包括如下: Who,即主体(Subject),主体一般是指用户 ...

随机推荐

  1. Canvas知识点补充

    Canvas笔记 复习 初识canvas <canvas> 是 HTML5 新增的,一个可以使用脚本(通常为 JavaScript) 在其中绘制图像的 HTML 元素.它可以用来制作照片集 ...

  2. PAM学习笔记

    想了想 还是要先把字符串的东西先都学完告一段落了再说 时间不多了 加油~. PAM 回文自动机 比SAM简单到不知道哪里去了. 回文自动机和其他自动机一样有字符集 有状态 有转移. 一个字符串的回文自 ...

  3. Hadoop学习问题记录之基础篇

    目的 记录学习hadoop过程中遇到的基础问题,无关大小.无关困扰时间长短. 问题一 全分布式环境中运行mapred程序,报异常:java.net.NoRouteToHostException: 没有 ...

  4. day1. python注释及变量

    一.注释 1.单行注释 # # python 2.x print "你好" # python 3.x print("你好") 2.多行注释 ''' '''  或 ...

  5. squid正向代理访问外网

    目录 一.前言 二.Squid安装 三.客户端设置 四.验证 五.Python请求 六.写在最后 一.前言 1)我们可能会碰到这样的需求,客户端Client-1需要访问Server-1,但由于各种各样 ...

  6. 3月21日考试 题解(数据结构+区间DP+贪心)

    前言:T3写挂了,有点难受. --------------- T1 中位数 题意简述:给你一段长度为$n$的序列,分别输出$[1,2k-1]$的中位数$(2k-1\leq n)$. --------- ...

  7. 如何打印完整的MYSQL带参数SQL日志信息

    在mysql的jdbc中开启sql分析,如下: jdbc.url=jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=U ...

  8. Springboot使用Shiro-整合Redis作为缓存 解决定时刷新问题

    说在前面 (原文链接: https://blog.csdn.net/qq_34021712/article/details/80774649)本来的整合过程是顺着博客的顺序来的,越往下,集成的越多,由 ...

  9. CSS表单与数据表(上)

    表单在现代Web应用中占据着重要地位. 表单可以很简单,也可以非常复杂,要横跨几个页面. 除了从用户哪里获得数据,Web应用还需要以容易看懂的方式展示数据.表格是展示复杂数据的最佳方式. 1.设计数据 ...

  10. Vue老项目支持Webpack打包

    1.老的vue项目支持webpack打包 最近在学习Vue.js.版本是2.6,webpack的版本也相对较老,是2.1.0版本.项目脚手架只配置了npm run dev和npm run build. ...