认证大全(想学习其他认证,请到此链接查看)
Oauth2认证 - 授权委托协议
讲解(Oauth2认证)
概述
参考视频: https://www.youtube.com/watch?v=T0h6A-M_WmI
参考书籍(有时间强烈建议去看一下通俗易懂而且有demo,不过不是java的而是nodejs版本): https://pan.baidu.com/s/1pPjgdWv-elnncb-Ckx7QZw?pwd=00dh === 提取码:00dh == OAuth2实战
官方定义规范文章(建议看=整体细节): https://datatracker.ietf.org/doc/rfc6749/
官方定义规范文章(建议看=Bearer令牌细节): https://datatracker.ietf.org/doc/rfc6750/
第三方网站的Oauth2的对接规范(微博-不想看官方直接看具体网站如何对接也大差不差): https://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6
第三方网站的Oauth2的对接规范(码云-不想看官方直接看具体网站如何对接也大差不差): https://gitee.com/api/v5/oauth_doc#/
第三方网站的Oauth2的对接规范(Github-不想看官方直接看具体网站如何对接也大差不差): https://docs.github.com/cn/developers/apps/building-oauth-apps/authorizing-oauth-apps
作用: 用户A授权委托网站B(拿到用户A在网站C的令牌)可以使用用户A在网站C的信息 == 委托协议、跨系统授权的方案的标准
官方RFC定义的Oauth2认证流程
官方RFC定义的Oauth2认证流程 == 结合访问token以及刷新token
微博Oauth2认证流程
码云Oauth2认证流程
客户端网站B利用reg刷新持有的网站C的access_token令牌(此过程无需用户参与)
授权(获取令牌)方式
网站B给网站C的参数 | 描述 |
---|---|
response_type | 必须,授权方式:code(授权码类型) |
client_id | 必须,网站B在网站C的客户端标识 |
redirect_uri | 可选,一般要求跟当时在网站C填写的回调地址一样 |
scope | 可选,请求资源范围,即需要申请的token需要什么权限 |
state | 可选,随机数 |
授权码授予(Authorization Code Grant)- 需浏览器用户、客户端、授权服务器三方参与
access_token: 网站C认证成功后,重定向到网站B的时候时会在url中携带过来code,然后网站B在服务器后台根据code,访问网站C的api获取用户的access_token
准则: 利用授权码或者刷新令牌获取访问令牌时,一旦校验错误,返回错误信息的响应报文,无论出于什么原因,授权服务器都必须将涉及到的授权码、刷新令牌信息删除,如授权码正确但是客户端ID错误、刷新令牌正确但客户端密钥错误的情况。
更详细的流程图-来自RFC文档协议图
更详细的流程图-来自书籍
隐式(简化)授予(Implicit Grant)- 需浏览器用户、客户端、授权服务器三方参与
access_token: 网站C认证成功后,重定向到网站B的时候时会在url中携带过来access_token
密码授予(Resource Owner Password Credentials Grant)- 需浏览器用户、客户端、授权服务器三方参与
access_token: 用户在网站B填入网站C的账户、密码信息,网站B使用网站C的API进行账号、密码校验,校验通过则返回用户的access_token
客户端授予(Client Credentials Grant)- 仅客户端、授权服务器两方参与(无浏览器用户参与)
access_token: 其实依然是密码授予模式,比如使用BasicAuth、DigestAuth,依然需要用户提供网站C的账户、密码信息
额外功能:客户端应用可自行注册到授权服务器(API接口方式)
背景: 无需用户、开发者干预,开发者事先对接好授权服务器的注册接口即可,程序启动部署自动注册
简易视图
参数信息
字段名 | 字段值 | 描述 |
---|---|---|
redirect_uris | ⼀个URI字符串数组,在基于重定向的OAuth许可类型中使⽤,⽐如authorization_code 和implicit | |
token_endpoint_auth_method | 客⼾端在令牌端点上进⾏⾝份认证的⽅式 | |
none | 客⼾端不在令牌端点上进身份认证,可能是因为客户端不使用令牌端点,或者使用令牌端点但它是公开客户端 | |
client_secret_basic | 客户端使⽤HTTP Basic发送其客户端密钥。如果不指定且已为客户端颁发了密钥,则默认为此值 | |
client_secret_post | 客⼾端使⽤表单参数发送客⼾端密钥 | |
client_secret_jwt | 客户端会创建一个用客户端密钥进行对称签名的JSON Web令牌(JWT) | |
private_key_jwt | 客户端会创建一个用客户端私钥进行非对称签名的JSON Web令牌(JWT)。客户端需要在授权服务器上注册自己的公钥 | |
grant_types | 客户端获取令牌所使用的许可类型。该字段使用的值与令牌端点上grant_type 参数使用的值相同 | |
authorization_code | 授权码许可,客户端将资源拥有者引导至授权端点,获取授权码,然后将授权码发回⾄令牌端点。需要对应使⽤的response_type 为“code” | |
implicit | 隐式许可,客⼾端将资源拥有者引导⾄授权端点,直接获取令牌。需要对应使⽤的response_type 为“token” | |
password | 资源拥有者密码许可,客户端向资源拥有者索取他们的用户名和密码,用于在令牌端点上换取令牌 | |
client_credentials | 客户端凭据许可,客户端使用自己的凭据获取令牌 | |
refresh_token | 刷新令牌许可,在资源拥有者不在场的情况下,客户端使用刷新令牌获取新的访问令牌 | |
urn:ietf:params:oauth:grant-type:jwt-bearer | JWT断言许可,客户端通过出示带有特定声明的JWT来获取令牌 | |
urn:ietf:params:oauth:grant-type:saml2-bearer | SAML断言许可,客户端通过出示带有特定声明的SAML文档来获取令牌 | |
response_types | 客户端使用的授权端点响应类型。该字段使用的值与response_type 参数使用的值相同 | |
code | 授权码响应类型,该类型会返回授权码,该授权码会被传递至令牌端点用于获取令牌 | |
token | 隐式响应类型,该类型会直接向重定向URI 返回令牌 | |
client_name | 可读的客⼾端显⽰名称 | |
client_uri | 指向客⼾端主⻚⾯的URI | |
logo_uri | 客户端图形标志的URI。授权服务器可以使用该URI向用户展示客户端的标志,但需要注意的是,获取图片URI资源可能会给用户带来安全和隐私方面的问题 | |
scope | 客⼾端请求令牌时所有可⽤的权限范围。它的值是以空格分隔的字符串,与OAuth协议中的同名字段⼀样 | |
contacts | 客⼾端负责⼈员的联系⽅式列表。通常是电⼦邮箱地址,但也可能是电话号码,即时通信地址或者其他联系⽅式 | |
tos_uri | ⼀个可读⻚⾯的URI,该⻚⾯列出了客⼾端服务条款。这些条款描述了资源拥有者对客⼾端授权时要接受的契约关系 | |
policy_uri | ⼀个可读⻚⾯的URI,该⻚⾯包含客⼾端的隐私策略。该策略描述了部署客⼾端的机构如何搜集、使⽤、保留以及公开资源拥有者的个⼈数据,包括通过授权API获取的数据 | |
jwks_uri | ⼀个指向JSON Web密钥集合的URI,该密钥集合包含此客⼾端的公钥,可被授权服务器访问。该字段不能与jwks ⼀起使⽤。优先使⽤jwks_uri 字段,因为它能让客⼾端轮换密钥 | |
jwks | ⼀个JSON Web密钥集合⽂档(JSON对象),包含此客⼾端的公钥。该字段不能与jwks_uri ⼀起使⽤。优先使⽤jwks_uri 字段,因为它能让客⼾端轮换密钥 | |
software_id | 客⼾端软件的唯⼀标识符。该标识符在同⼀个客⼾端软件的所有实例上都是相同的 | |
software_version | software_id 字段所标识的客⼾端软件的版本标识。版本字符串对授权服务器是不透明的,也不会假设它具有特定格式 |
安全准则
安全整改1 - 严格遵守规则
安全整改2 - 流程优化(PKCE)
讲解: code_challenge_method标识code_challenge、code_verifier校验关系,比如说code_challenge_method=sha-256,则授权服务器是校验 sha256(code_challenge) 与 code_verifier 是否一致,一致才给客户端生成令牌。当然code_challenge、code_verifier可以是一样,比对是否一致也行,主要看你校验策略
代码实现
oauth第三方客户端(类比csdn端(因为支持第三方登录-微信扫码登录)): https://gitee.com/changenen/oauth-client-project
oauth授权端、以及保护资源端(类比微信端): https://gitee.com/changenen/oauth-client-project
注意: 本demo只是实现oauth常用的一些功能,虽然看起来不难但是实现起来也是花了不少心血。更高级的功能比如自定义授权权限,客户端自行注册到授权服务器,pkce校验是否都没在代码中实现,如果有兴趣可自行参考前面说的《oauth2实战》书籍进行增强编写即可