1

首先介绍几个易混淆的概念。
认证与授权
认证(Authentication):通过认证以确定用户身份,认证可以理解为用户登录过程。
授权(Authorization):给用户分配可权限,以确定用户可访问的资源范围。授权的前提是要确认用户身份,即先认证,再授权。

OpenID、OpenID Connect、OAuth2.0
OpenID、OpenID Connect:提供第三方认证的协议规范,第三方认证也可以理解为单点登录SSO,即一个认证服务和多个业务应用。用户在认证中心登录,业务应用通过认证中心接口获取用户身份信息,典型场景为企业内部Web系统集成单点登录,典型的有CAS。
OAuth2.0:向第三方系统提供授权(访问自身)服务的协议规范。通过向第三方系统提供Token,以便在不向第三方系统提供自身密码的情况下,授权第三方系统访问自身的部分服务。

OpenID vs OpenID Connect
OpenID:由OpenID基金会维护的第三方认证规范,存在如下缺点:

  1. 以URI为用户唯一标识,用户难以记忆
  2. 第三方应用必须是网站,没有提供API,不支持移动应用
  3. 不支持健壮的加密和签名

OpenID Connect:基于OAuth2.0实现的用户认证规范。相对OpenID提供了如下增强特性。

  1. 提供可扩展性,运行人们通过任何OpenID Connect Provider进行身份验证,而不是仅限于Google、Facebook等主流IDP。
  2. 电子邮件作为用户标识,便于用户记忆。
  3. 允许客户端动态注册,减轻管理员显示注册设备和网站的工作量。

一个授权服务如何为第三方提供认证服务?
OpenID Connect对OAuth2.0接口进行了扩展,通过在协议中扩展身份认证所需的ID Token字段,增加UserInfo Endpoint接口,向第三方应用提供身份认证服务。

  1. 用户执行OAuth2.0的授权流程后,第三方应用获得Access Token和附加的ID Token,ID Token包含基本的用户身份信息,可用于身份认证。
  2. 如果需要更详细用户信息,第三方应用通过Access Token,从认证服务UserInfo Endpoint接口获取用户信息。
  3. 第三方应用可以把ID Token和UserInfo信息作为认证用户的用户信息。

OpenID Connect基础

OpenID Connect(简称OIDC)是一种安全认证机制,第三方应用连接到身份认证服务器(Identify Service)获取用户信息,并把这些信息以安全可靠的方式返回给第三方应用。

OAuth2.0通过Access Token作为向第三方应用授权访问自身资源的凭证。OpenID Connect对OAuth2.0进行协议进行了扩展,通过扩展的ID Token字段,提供用户基础身份信息,ID Token使用JWT(JSON Web Token)格式进行封装,提供自包含性、防篡改机制,可以安全的传递给第三方应用程序并容易被验证。除了ID Token,还可以通过Access Token从认证服务的UserInfo Endpoint接口获取更详细的用户信息。

相关概念
End User(EU):被认证的用户。
Relying Party(RP):OpenID Connect客户端,即需要认证服务的第三方应用,身份认证服务的消费者。
OpenID Provider(OP):提供身份认证的服务,为RP提供EU的身份认证信息,又称Identify Provider。
ID Token:JWT格式封装的EU用户身份认证信息JSON。
UserInfo Endpoint:查询用户信息接口,返回当前Access Token对应授权用户的信息。

OpenID Connect认证模式
OAuth2.0提供了四种授权模式,分别为授权代码模式(Authorization code)、隐含模式(Implicit)、资源所有者密码凭据模式(Resource Owner Password)和客户端凭据模式(Client Credentials)。由于资源所有者密码凭据模式直接向第三方应用提供了密码,客户端凭据模式直接信任第三方应用,这两种模式下无需再进行附加认证。所以OpenID Connect提供了授权代码模式(Authorization code)、隐含模式(Implicit)两种认证模式,还有一种混合模式(两种模式的混合),认证的流程和OAuth2.0的流程基本一致,附加了ID Token和UserInfo Endpoint接口。

认证流程概览
详细流程说明请参考 OpenID Connect Core 1.0规范

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

The OpenID Connect protocol, in abstract, follows the following steps.

  1. The RP (Client) sends a request to the OpenID Provider (OP).
  2. The OP authenticates the End-User and obtains authorization.
  3. The OP responds with an ID Token and usually an Access Token.
  4. The RP can send a request with the Access Token to the UserInfo Endpoint.
  5. The UserInfo Endpoint returns Claims about the End-User.

认证代码模式(### Authorization Code)

由于OpenID Connect的认证流程和OAuth2.0的授权流程基本一致,此处不再介绍详细的流程,只说明差异部分,关于OAuth2.0的授权流程,可以参考 OAuth 2.0认证框架介绍

认证代码模式的整体认证步骤如下:

  1. Client准备认证相关的请求参数。
  2. Client向授权服务器(Authorization Server)请求认证。
  3. 授权服务器认证(登录)用户。
  4. 用户确认给Client授权并确认。
  5. 授权服务器把用户重定向回Client,URL中携带授权代码。
  6. Client(服务器端)通过授权代码,向Token Endpoint发送请求。
  7. Token Endpoint接口返回ID Token和Access Token。
  8. Client校验ID Token,并从中提取用户的身份标识(Subject Identifier)。

差异点:

  1. 获取认证代码请求(第2步)中,scope必须包含openid字段。
  HTTP/1.1 302 Found
  Location: https://server.example.com/authorize?
    response_type=code
    &scope=openid%20profile%20email
    &client_id=s6BhdRkqt3
    &state=af0ifjsldkj
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
  1. Token Endpoint接口返回数据中,和OAuth2.0比,增加了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"
  }

其他步骤基本一致。

ID Token

ID Token是JWS(JSON Web Signature)格式的字符串,相关规范可参考 JSON Web Signature草案,JWS字符串有三部分组成,分别为JWS Protected Header、JWS Payload、JWS Signature,三部分内容分别Base64编码后通过点(.)拼接,拼接公式如下:

      BASE64URL(UTF8(JWS Protected Header)) || '.' ||
      BASE64URL(JWS Payload) || '.' ||
      BASE64URL(JWS Signature)
JWS可以通过JWS Signature来校验数据的完整性,但不提供机密性。

JWS Payload是ID Token的内容部分,是一个JSON对象,包括如下字段:

字段含义
iss(Issuer Identifier)ID Token颁发者的标识符,一般为认证服务器的URL。
sub(Subject Identifier)认证用户(End User)标识符,全局唯一。
aud(Audience(s))ID Token的受众,必须包含第三方应用的client_id。
exp(Expiration time)Token过期时间。
iat(Issued At Time)JWT生成时间。
nonce随机数,防重放攻击。
auth_time(Authentication Time)用户认证发送时间。
acr(Authentication Context Class Reference)表示一个认证上下文引用值,用以标识认证上下文类。
amr(Authentication Methods References)一组认证方法。
azp(Authorized party)结合aud使用,只有在被认证的一方和受众(aud)不一致时才使用此值,一般情况下很少使用。

乘着风
107 声望12 粉丝

五岁时,妈妈告诉我,人生的关键在于快乐。上学后,人们问我长大了要做什么,我写下“快乐”。他们告诉我,我理解错了题目,我告诉他们,他们理解错了人生。——约翰·列侬