我这里试着把协议分为几大类 :
这一篇我们只对流程进行一个普及 , 后面陆陆续续来分析一下其中的实现方式.
Token 是认证过程中最常见的一个概念 , 它没有特定的规范 , 它仅仅是一个有着不同协议特征的钥匙 . 通常而言 , 他是有一定规律的无意义的字符串
JWT 全称 Json web token , JWT 通常由三部分组成 :
纯约束型表示其长得就像个规范 ,而不同的框架去实现这个规范 (其实规范也叫框架 , 是一种狭义的框架)
通常我们说的 OAuth 是指其 2.0 版本 , 现在OAuth 已经公布了其 2.1 的版本 , 在结构上做了简化 , OAuth 其实不是一个完整的概念 , 它实际上是由许多不同的 rfc 组成的 (RFC 6749 , RFC 6750),它们以不同的方式相互构建并添加特性 , 就如下图所示 :
@ aaronparecki.com/2019/12/12/…
在整个 OAuth 协议的发展中 , 他被陆陆续续添加了多个规范 , 并且实现了多种功能.
例如 RFC 6749 中就定义了我们用的最多的四种授权类型: 授权代码、隐式、密码和客户端凭据 , 而 RFC 7636 中则加入了 PKCE (一种无需客户机机密就可以使用授权代码流的方法) , RFC 8252 中将其建议为本机应用程序使用 .
>>> 直到陆陆续续到了 OAuth2.1 , 还剩下以下三种类型 :
这一篇不会涉及到过多的 OAuth2.1 , 主要是我的实现代码还没有写完...
OAuth2.0 支持的类型 :
OAuth 的整个流程大概就长下面那样 :
OAuth2.0 的流程网络上已经说的太多了 ,自认为不会被前辈们画的更好 , 这里也就直接引用了:
总结性归类 :
这里细说一下三者的区别 :
Code 方式 :
Code 方式一般是企业最常用的一种方式 , 因为它很灵活 , 安全性也高 , 它和 implicit 以及 password 模式的区别主要是多了一个获取 Code 的过程 :
Step 1: Authoriza - > code : 发起请求返回code
Step 2: Code -> Token : 传递Code 换取Toekn
Step 3: Token -> UserInfo : 传递Token 换取用户信息
implicit 方式 :
implicit 方式是相对于 Code 的简化版 , 它由 Step1 Authoriza 直接来到了Token 步骤
password 方式 :
password 方式就变化较大了 ,它省去了跳转登录页认证的步骤 , 直接获取Token
OAuth Code 方式
OAuth implicit 方式
OAuth Password 方式
OAuth 协议的接口请求一览
// Authoriza Code 模式
* 第一步 : http://localhost:8080/oauth/authorize?response_type=code&client_id=pair&redirect_uri=http://baidu.com
> Response_type -> 返回类型
> Client_id-> 对应的client id
> redirect_uri->重定向的地址
* 第二步 :
http://localhost:8080/oauth/token?grant_type=authorization_code&code=o4YrCS&client_id=pair&client_secret=secret&redirect_uri=http://baidu.com
> grant_type
> code
> client_id
> client_secret
> redirect_uri
* 第三步 :
通过Token 换取信息 ... 略
----------------------------
// implicit 模式 (略 , 第一步直接返回Code)
----------------------------
// Password 模式 (直接传入密码)
http://localhost:8080/oauth/accessToken?grant_type=password&client_id=b7a8cc2a-5dec-4a64&username=admin&password=123456
问题一 : state 的作用 问题 : 当被攻击人(平民 A )登录时 ,让 A 认为登录的是自己的账号 ,但是 ,实际上 ,登录的是 攻击者 (狼人B)事先准备的账号 ,这就导致 A 在其上做的操作 ,B均可见 。
这就是通常说的中间人攻击 , 而有了 state , 开发者可以用这个参数验证请求有效性,也可以记录用户请求授权页前的位置 , 当然 ,也可以预防 CSRF
问题二 : implicit 和 Password 存在的场景 ?
Password 从请求上就可以看出有一定的安全漏洞 ,如果没有 SSL + 明文密码 , 这简直是把密码告诉别人了 , 而在我的使用中, 部分应用是发起存后台请求 , 不期望进行跳转 , 这个时候 , password 就能派上用场
问题三 : 待完善 TODO ~~~~~
讲了 OAuth 当然要来说一下 OIDC 这个小兄弟啦 , OIDC 其实很简单 , 就是在 OAuth 的基础上加入了 OpenID 的概念 , 你如果为了方便 , 复用 OAuth 的代码都没问题的. 即在 OAuth 的基础上额外携带一个 JWT 传递用户信息
OpenID Connetction : OIDC= (Identity, Authentication) + OAuth 2.0 , 它是一个基于 OAuth 2 的身份认证标准协议 , 通过 OAuth 2.0 构建了一个身份层 .
OIDC 提供了ID Token 来解决第三方客户端标识用户身份 的问题 ,在Oauth2 的授权流程中 ,一并提供用户的身份认证信息给第三方客户端 ,ID token 使用JWT 格式进行包装 (得益于 JWT 的包容性 紧凑性 和 防篡改机制 ,并且提供 UserInfo ,可以回看一下开头的 JWT 扩展哦 )
OIDC 构成 信息
- core : 定义 OIDC 的核心功能 ,在OAuth 2 之上 构建身份认证 ,以及使用 Claims 来传递用户信息
- Discovery : 发现服务 , 用于客户端动态的获取OIDC 服务相关的元数据描述信息
- Dynamic Registration : 动态注册服务 , 使客户端可以动态的注册到OIDC 的 OP
- OAuth 2.0 Multiple Response Types :可选。针对OAuth2的扩展,提供几个新的response_type。
- OAuth 2.0 Form Post Response Mode:可选。针对OAuth2的扩展,OAuth2回传信息给客户端是通过URL的querystring和fragment这两种方式,这个扩展标准提供了一基于form表单的形式把数据post给客户端的机制。
- Session Management :可选。Session管理,用于规范OIDC服务如何管理Session信息
- Front-Channel Logout:可选。基于前端的注销机制,使得RP(这个缩写后面会解释)可以不使用OP的iframe来退出
- Back-Channel Logout:可选。基于后端的注销机制,定义了RP和OP直接如何通信来完成注销
The RP (Client) sends a request to the OpenID Provider (OP).
The OP authenticates the End-User and obtains authorization.
The OP responds with an ID Token and usually an Access Token.
The RP can send a request with the Access Token to the UserInfo Endpoint.
The UserInfo Endpoint returns Claims about the End-User.
+--------+ +--------+
| | | |
| |---------(1) AuthN Request-------->| |
| | | |
| | +--------+ | |
| | | | | |
| | | End- |<--(2) AuthN & AuthZ-->| |
| | | User | | |
| RP | | | | OP |
| | +--------+ | |
| | | |
| |<--------(3) AuthN Response--------| |
| | | |
| |---------(4) UserInfo Request----->| |
| | | |
| |<--------(5) UserInfo Response-----| |
| | | |
+--------+ +--------+
// 详细步骤 :
》 OIDC 单点登录流程
> 1 . 用户点击登录 ,触发对OIDC-SERVER 的认证请求
|-> request : 包含参数URL , 指向登录成功后的跳转地址
|-> response : 返回 302 ,Location 指向 OIDC-SERVER ,Set-Cookie 设置了 nonce的cookie
> 2 . 向 OIDC-SERVER 发起 authc 请求
|-> client_id=implicit-client :发起认证请求的客户端的唯一标识
|-> reponse_mode=form_post :使用form表单的形式返回数据
|-> response_type=id_token :返回包含类型 id_token
|-> scope=openid profile :返回包含有openid这一项
|-> state :等同于OAuth2 state ,用于保证客户端一致性
|-> nonce : 写入的cookie 值
|-> redirect_uri : 认证成功后的回调地址
> 3 . OIDC-SERVER 验证 authc 请求
|-> client_id是否有效,redircet_uri是否合法 等一系列验证
> 4 . 引导用户登录 ,以及用户登录
|-> resumeURL
|-> username + password
> 5 . 返回一个自动提交form 表单的页面
|-> id_token:id_token即为认证的信息,OIDC的核心部分,采用JWT格式包装的一个字符串
|-> scope:用户允许访问的scope信息
|-> state : 类似
|-> session_state :会话状态
> 6 . 验证数据有效性,构造自身登录状态
|-> 客户端验证id_token的有效性 ,保证客户端得到的id_token是oidc-sercer.dev颁发的
OIDC 接口演示 ------------> 真不记得是哪位大佬的案例了....
// OIDC 直观流程 请求地址 :
// Step 1 : 发起 Authorize 请求
https://${yourDomain}/oauth2/default/v1/authorize?response_type=code
&client_id=12345
&redirect_uri=https://proxy.example.com:3080/v1/webapi/oidc/callback
&scope=openid,email
&state=syl
// Step 2 : 认证成功后重定向返回
https://proxy.example.com:3080/v1/webapi/oidc/callback?code=pkzdZumQi1&state=syl
// Step 3 : 申请 Token
POST https://${yourOktaDomain}/oauth2/default/v1/token
?grant_type=authorization_code&
code=pkzdZumQi1&
redirect_uri=https://proxy.example.com:3080/v1/webapi/oidc/callback
client_id=12345&
client_secret=gravitational
// Step 4 : AccessToken 返回
{
"id_token":"FW6AlBeyalZtDIRXxA0u5XBbZkLzjYzKUQBloxQXSSGPFmRS8eSfDu0A4nS4GF1aQP9PRxQk7gIh9bjaX99
aa4vDSzP1E2ajsgIomlNGhNxBqEDV5Exp0xISE9bZ4HUzM91pbzPPj7Bq5ZQUWcSuSVD0NAfkAoG6qDpbQfxPjWRyfthz3p
UEXwZe8Cz4eOXOM45UKB4Q0VnVSChVF84MWkeBFKzhrRNXd2dFv0HTlkQr6vXGlYsocMxR06wo38HvGiKjkUmL2YUyPOjZa
oUN4ovfwlwdGdjNR2GVcRsXzjxCPszJ9dTXztoL5wo2ycEpuxkkNp57BuZ9YRexoNnRHahFKH76XrFsTvdvAYk3fBVUqrO5
vvyxHAFrAIKpV0FvaMiBwKNfaE84oRC6aBXnzS3q4uVyGcHveHQMJB1temgB599rfVH3pBqurUmQCd0tVexRZj4PUkrDocf
8Z0QKkCD0eonH0Q1bRpQPY5vATiLkpF8RArU7wyB2FxhB3egtQBvwDgsVjyix7u8Cx4P9oy3IJje6SZfc6Lz61uEQttpVhy
qfzgFYUqVoQacw6rocCn3u61dM0moB"
"access_token":"IEZKr6ePPtxZBEd",
"token_type":"bearer",
"scope":"read:org",
"expires_in":3600
}
// Step 5 : 对 id_token 进行解码
{
"sub":"virag",
"iss":"https://${yourOktaDomain}/oauth2/",
"aud":"client_12345",
"iat":"1595977376",
"exp":"1595980976",
"email":"virag@goteleport.com",
"email_verified":"true"
}
// Step 6 : 对资源进行请求
https://www.ubisecure.com/education/differences-between-saml-oauth-openid-connect/
https://www.okta.com/identity-101/whats-the-difference-between-oauth-openid-connect-and-saml/
https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols
https://yangsa.azurewebsites.net/index.php/2019/08/08/brief-summary-of-differences-between-oauth2-and-oidc/
https://www.c-sharpcorner.com/article/oauth2-0-and-openid-connect-oidc-core-concepts-what-why-how/
OIDC Discovery 规范
定义了一个服务发现的规范,它定义了一个api( /.well-known/openid-configuration ),这个api返回一个json数据结构,其中包含了一些OIDC中提供的服务以及其支持情况的描述信息,这样可以使得oidc服务的RP可以不再硬编码OIDC服务接口信息
会话管理
OIDC 的好处
CAS 我可太熟了 , 这还不随便和大家扯淡~~~~
CAS分为两部分,CAS Server和CAS Client
CAS 的三个术语
我知道一般人懒得看 ,我也是 ,所以我画了一张图!!!
CAS 与 OAuth 最大的几个区别 :
CAS 和 OAuth 都是一种认证结构/协议 , 而 Token/ST则是属于一种票据的方式 , 并没有特定的归属
CAS 认证的票据 :
CAS 通过将 TGC 写入 Cookie , 当下次认证是从 Cookie 中取出 TGC 认证 ,所以要想做跨浏览器登录 , 可以在这里做文章哦 !
今天先这样了 , 又要到转钟了 , 这篇文章既是盘点 , 也是对自身知识图谱的完善 , 认证协议多种多样 , 常规的应用通常只需要选择其中最合适的一种去实现自己的业务即可.
阅读量:2017
点赞量:0
收藏量:0