Identity Server 4 预备知识 -- OpenID Connect 简介

我以前的文章简单的介绍了OAuth 2.0 (在这里: http://www.noobyard.com/article/p-vpdnfqeb-ch.html), 还不是很全.html

这篇文章我要介绍一下 OpenID Connect.web

OAuth 2.0 不是身份认证协议

OAuth 2.0 不是身份认证(Authentication)协议. 为何有人会认为OAuth 2.0具备身份认证的功能? 这是由于OAuth2常常做为身份认证(Authentication)协议的一部分来使用. 例如在典型的OAuth2流程里, OAuth2常常会嵌入一些身份认证的事件.浏览器

那么身份认证(Authentication)是什么?安全

咱们这里所说的身份认证就是指它能够告诉应用程序当前的用户是谁, 还有这些用户是否正在使用你的应用程序. 它是一种安全架构, 它能够告诉你用户是他们所声明的身份, 一般呢, 是经过提供一套安全凭据(例如用户名和密码)给应用程序来证实这一点.服务器

而OAuth2则无论用户这些东西, OAuth2的客户端应用只考虑请求token, 获得token, 使用token访问API. 它不关心谁给客户端应用受权了, 也不关心是否有最终用户.\架构

 

身份认证(Authentication) vs 受权(Authorization)

引用《OAuth 2.0 in Action》里面的一个比喻来解释, 把身份认证看做是软糖, 而受权是巧克力. 这两种东西感受略有类似, 可是本质上却大相径庭: 巧克力是一种原料, 而软糖是一种糖果. 可使用巧克力做为主要原料作出巧克力口味的糖果, 可是巧克力和软糖毫不是等价的.ide

尽管巧克力能够单独做为一种最终产品, 但在这个比喻里巧克力是一种很是有用原料, 它极具多样性, 能够用来作蛋糕, 冰激凌, 雪糕等等.web安全

 

在这个比喻里 OAuth 2.0 就是巧克力, 它是众多web安全架构的一种多用途的基本成分.spa

而软糖, 是一种糖果. 有一种特别可口的软糖叫作巧克力软糖. 很显然, 巧克力在这种软糖里是主要成分, 可是它还须要其它原料成分和一些关键的流程把巧克力转化成巧克力软糖.code

制作出的产品是软糖的形式, 它以巧克力为主要成分. 这叫使用巧克力来制做软糖, 因此说巧克力不等价于软糖.

在这个比喻里, 身份认证就更像软糖, 它须要一些关键的组件和流程, 而却要把这些组件和流程经过正确的组合起来并安全的使用, 针对这些组件和流程仍是有不少的选项的.

能够说咱们要制做巧克力软糖, 也就是须要一个基于OAuth2的身份认证协议. 而OpenID Connect就是这样的开放标准, 它能够工做于不一样的身份供应商之间. OpenID Connect 基于 OAuth 2.0, 在此之上, 它添加了一些组件来提供身份认证的能力.

 

OpenID Connect的官方定义是: OpenID Connect是创建在OAuth 2.0协议上的一个简单的身份标识层, OpenID Connect 兼容 OAuth 2.0

 

OAuth 2.0与身份认证协议的角色映射

想要基于OAuth2构建身份认证协议, 那么就须要把OAuth2里面的那些角色映射到身份认证的事务里面.

在OAuth2里面, 资源全部者(Resource Owner)和客户端应用(Client)常常在一块儿工做, 由于客户端应用表明了资源全部者. 而受权服务器(Authorization Server)和被保护的资源(Protected Resource)常常在一块儿, 由于受权服务器生成token, 而被保护的资源接收token. 因此说在最终用户/客户端应用 与 受权服务器/被保护资源 以前存在一个安全和信任的边界, 而OAuth2就是用来跨越这个边界的协议.

而在身份认证的事务里, 最终用户使用身份提供商(Identity Provider, IdP)登陆到依赖方(Relying Party, RP, 能够理解为客户端).

总结一下前面这段话:

OAuth2里能够分为两部分: 1.资源全部者/客户端应用, 2.受权服务器/被保护资源.

身份认证协议里也是两大部分: 1.依赖方, 2.身份提供商.

因此考虑这样映射:

  • OAuth2里的受权服务器/被保护资源 ---- 身份认证协议里的身份提供商进行映射
  • OAuth2里面的资源全部者 ---- 身份认证协议里的最终用户
  • OAuth2的客户端应用 ---- 身份认证协议里的依赖方(RP).

OAuth2里, 资源全部者的权限会委派给客户端应用, 但这时该权限对应的被保护资源就是他们本身的身份信息. 也就是说他们受权给依赖方(RP), 让其能够知道如今是谁在使用应用, 而这就是身份认证事务本质.

依赖方如今就能够知道是谁在使用系统而且他们是如何登陆进来的. 不过这里还须要用到另一种token, 叫作ID token, 这种token携带着身份认证事件自己的信息.

那么为何不使用OAuth2里的access token把这些事都一次性解决了呢? 

由于首先access token不含有任何关于身份认证的信息; 其次access token的生命期可能会很是的长, 即便用户离开了它仍有可能有效, 它还有可能被用于无最终用户参与的状况; 还有一种状况就是access token可能会被其它的客户端应用借用. 因此, 不管客户端是如何获得的access token, 它都没法从access token里获得最终用户的信息以及最终用户的身份认证状态.

在OAuth2里, access token不是为客户端准备的, 它对于客户端应该是不透明的, 可是客户端也须要从access token获得一些用户信息. 实际上客户端应用只是access token的展现者, access token真正的目标观众是被保护的资源.

在OpenID Connect里, 这个第二个叫作ID Token, 它会和access token一同发送给客户端应用.

 

OpenID Connect

OpenID Connect是由OpenID基金会于2014年发布的一个开放标准, 简单的说就是, 它使用OAuth2来进行身份认证. OpenID Connect直接构建于OAuth2.0的基础之上, 与其兼容. 一般OpenID Connect是和OAuth2一同部署来使用的.

 

OpenID Connect的总体抽象流程以下图所示: 

1. 依赖发(RP)发送请求到OpenID提供商(OP, 也就是身份提供商).

2. OpenID提供商验证最终用户的身份, 并得到了用户委派的受权

3. OpenID提供商返回响应, 里面带着ID Token, 也一般带着Access Token.

4. 依赖方如今可使用Access Token发送请求到用户信息的端点.

5. 用户信息端点返回用户的声明(claims, 至关因而用户的信息).

 

OpenID Connect的ID Token 和用户信息端点之后在使用Identity Server 4的时候在进行介绍.

 

身份认证

OpenID Connect 会负责身份认证这个动做, 也就是把最终用户登陆到系统, 或者判断最终用户是否已经登陆了. OpenID Connect会经过一种安全的方式从服务器把身份认证的结果返回给客户端, 这样客户端就能够依赖于它了. 也是由于这个缘由, 客户端被称为了依赖方(RP). 这个身份认证的结果就是ID Token.

OpenID Connect身份认证有三个路径(三个流程, flow): Authorization Code 流程, Implicit 流程, Hybrid 流程.

 

Authorization Code Flow

在Authorization Code 流程里, 一个受权码(Authorization Code)会被返回给客户端. 这个受权码能够被直接用来交换ID Token和Access Token. 该流程也能够在客户端使用受权码兑换Access Token以前对其身份认证. 可是该流程要求客户端的身份认证动做在后台使用client id和secret来得到tokens, 这样就不会把tokens暴露给浏览器或其它可访问浏览器的恶意应用了.

这种流程要求客户端应用能够安全的在它和受权服务器之间维护客户端的secret, 也就是说只适合这样的客户端应用.

它还适合于长时间的访问(经过refresh token).

Authorization Code流程的受权码来自于受权端点, 而全部的tokens都来自于Token端点. 

Authorization Code流程的步骤以下:

  1. 客户端准备身份认证请求, 请求里包含所需的参数
  2. 客户端发送请求到受权服务器
  3. 受权服务器对最终用户进行身份认证
  4. 受权服务器得到最终用户的赞成/受权
  5. 受权服务器把最终用户发送回客户端, 同时带着受权码
  6. 客户端使用受权码向Token端点请求一个响应
  7. 客户端接收到响应, 响应的body里面包含着ID Token 和 Access Token
  8. 客户端验证ID Token, 并得到用户的一些身份信息.

 

Implicit Flow

Implicit流程在请求token的时候不须要明确的客户端身份认证, 它使用重定向URI的方式来验证客户端的身份. 由于这一点, refresh token也就没法使用了, 这一样也不适合于长时间有效的access token.

在Implicit流程里, 全部的tokens都来自于受权端点, 而Token端点并无用到.

该流程主要用于浏览器内的应用, Access Token和ID Token一同被直接返回给客户端. 由于这个缘由, 这些tokens也会暴露于最终用户和能够访问该浏览器的其它应用了. 

它并不适合于长时间的访问.

Implicit流程的步骤以下:

  1. 客户端准备身份认证请求, 请求里包含所需的参数
  2. 客户端发送请求到受权服务器
  3. 受权服务器对最终用户进行身份认证
  4. 受权服务器得到最终用户的赞成/受权
  5. 受权服务器把最终用户发送回客户端, 同时带着ID Token. 若是也请求了Access Token的话, 那么Access Token也会一同返回.
  6. 客户端验证ID Token, 并得到用户的一些身份信息.

 

Hybrid Flow

Hybrid流程是前二者的混合, 在该流程里, 有一些tokens和受权码来自于受权端点, 而另一些tokens则来自于Token端点.

该流程容许客户端当即使用ID Token, 而且只须要一次往返便可得到受权码.

这种流程也要求客户端应用能够安全的维护secret.

它也适合于长时间的访问.

Hybrid流程的步骤以下:

  1. 客户端准备身份认证请求, 请求里包含所需的参数
  2. 客户端发送请求到受权服务器
  3. 受权服务器对最终用户进行身份认证
  4. 受权服务器得到最终用户的赞成/受权
  5. 受权服务器把最终用户发送回客户端, 同时带着受权码, 根据响应类型的不一样, 也可能还带着一个或者多个其它的参数.
  6. 客户端使用受权码向Token端点请求一个响应
  7. 客户端接收到响应, 响应的body里面包含着ID Token 和 Access Token
  8. 客户端验证ID Token, 并得到用户的一些身份信息.

 

三种流程特色的比较:

  Authorization Code Flow Implicit Flow Hybrid Flow
全部的tokens都来自于受权端点 no yes no
全部的tokens都来自于Token端点 yes no no
Tokens对浏览器隐藏 yes no no
客户端能够被认证 yes no yes
可使用Refresh Token yes no yes
只需一次往返通讯 no yes no
大部分通讯都是服务器对服务器 yes no 看状况

 

返回类型值的比较: 

"response_type" 的值 Flow
code  Authorization Code Flow
id_token  Implicit Flow
id_token token  Implicit Flow
code id_token  Hybrid Flow
code token  Hybrid Flow
code id_token token  Hybrid Flow

 

本文就简单介绍这些, OAuth 2.0 和 OpenID Connect 其他涉及到的内容会在后续Identity Server 4的系列文章里介绍.