当前位置:网站首页>[OAuth2] 20. OAuth2 Extended Protocol PKCE
[OAuth2] 20. OAuth2 Extended Protocol PKCE
2022-08-10 08:29:00 【Beicheng Xiaolin】
一、什么是PKCE
PKCE 全称是 Proof Key for Code Exchange(代码交换证明密钥), 在2015年发布, 它是 OAuth 2.0 核心的一个扩展协议, 所以可以和现有的授权模式结合使用,比如 Authorization Code + PKCE, 这也是最佳实践,PKCE 最初是为移动设备应用和本地应用创建的, 主要是为了减少公共客户端的授权码拦截攻击.
PKCEIn fact, mainly through the increase in the process of authorizationcode_challenge和code_verifierTwo elements to verify the entire process,防止codeinterception by a third party. 实际上它的原理是客户端提供一个自创建的证明给授权服务器, 授权服务器通过它来验证客户端,把访问令牌(access_token) 颁发给真实的客户端而不是伪造的.
参考
参考2
1、回顾OAuth2.0授权码模式流程:
https://www.rfc-editor.org/rfc/rfc6749
(A)The client requests authorization from the resource owner. Authorization requests can be made directly to the resource owner (如所示),Or preferably indirectly through authorization The server acts as an intermediary.
(B)The client receives an authorization grant,这是a Credentials representing the authorization of the resource owner, Represented using one of the four authorization types defined in this example The method used to specify or use the deferred grant type method determines the grant grant type
The client requests the type of authorization and support 授权服务器.
The client requests an access token through authentication 授权服务器,and give authorization.
(D)The authorization server authenticates and authenticates the client 授权授予,如果有效,An access token will be issued.
2、 授权码模式
- 1、客户端携带 client_id, scope, redirect_uri, state 等信息引导用户请求授权服务器的授权端点下发 code.
- 2、授权服务器验证客户端身份,验证通过则询问用户是否同意授权(此时会跳转到用户能够直观看到的授权页面,等待用户点击确认授权).
- 3、假设用户同意授权,此时授权服务器会将 code 和 state(如果客户端传递了该参数)拼接在 redirect_uri 后 面,以302(重定向)形式下发 code.
- 4、客户端携带 code, redirect_uri, 以及 client_secret 请求授权服务器的令牌端点下发 access_token.
- 5、授权服务器验证客户端身份,同时验证 code,以及 redirect_uri 是否与请求 code 时相同,验证通过后下发 access_token,并选择性下发 refresh_token,支持令牌的刷新.
参考
3、PKCE的流程
PKCEMainly by adding in the process of authorizationcode_challenge和code_verifierTwo elements to verify the entire process,防止codeinterception by a third party.具体流程如下:
That is, as originally requestedtoken中添加了code_challenge和code_verifier参数
- code_verifier
一个ClientA random string generated by the terminal(由字母,数字,- ,. , ,~ 组成).
调用应用程序(SPA)Created key,The key can be verified by the authorization server as the key is called Code Verifier(Code validator) - code_challenge
The calling application is Code Verifier Create a converted value,称为 Code Challenge,HTTPS Send this value(Code Challenge)去检索 Authorization Code.
This improves fetching from the authentication server token的安全性.
4、 PKCE的流程说明
- 1、 OAuth2客户端生成 code_verifier,并使用 code_challenge_method 计算 code_challenge,具体的算法稍后会详细讲解.
- 2、OAuth2客户端发起/oauth2/authorize授权请求,携带 code_challenge 和 code_challenge_method 这两个参数.
- 3、OAuth2授权服务器对OAuth2客户端/oauth2/authorize的授权请求进行验证.
- 4、 OAuth2Authorization server check code_challenge 和 code_challenge_method 是否存在.
- 5、 如果步骤4These two parameters exist,The authorization server is persistentcode_challenge 和 code_challenge_method这两个参数.
- 6、然后OAuth2The authorization server responds to the authorization code request.
- 7、 OAuth2The client receives the authorization code response and starts the call/oauth2/token请求访问令牌,The request requires additional appendages generated in the initial requestcode_verifier参数.
- 8、 OAuth2The authorization server received an access token request,used in the requestcode_verifier和步骤5持久化的code_challenge_methodPerform a digest calculation to generate a check string,The check string must sum the steps5持久化的code_challenge进行匹配校验.
- 29、如果步骤8The match check in is successful,则发放访问令牌access_token,Otherwise the request is rejected.
5、PKCE请求演示
5.1 没有PKCE的授权请求:
http://localhost:9000/oauth2/authorize?response_type=code&client_id=felord&scope=message.read message.write&state=46ge_TeI-dHuAnyv67nVmCcAmFgCVSZAqjTi9Om-1aA=&redirect_uri=http://127.0.0.1:8082/test/bar
5.2 有PKCE的授权请求:
http://localhost:9000/oauth2/authorize?response_type=code&client_id=felord&scope=message.read%20message.write&state=NAqBLbmooEhMPGELwleACOHvybODP_hctqV-PuNjuxo%3D&redirect_uri=http://127.0.0.1:8082/test/bar&code_challenge=mQ4xjFrCXg-1P4iURSXcSCmGVc-dloG0b0sdGpICrN0&code_challenge_method=S256
6、Spring Security PKCE的实现
pkce 分支
6.1、 OAuth2 客户端配置
OAuth2Client to generatecode_verifier,并使用 code_challenge_method 计算 code_challenge,And encapsulate it into the authorization request parameter,需要改造OAuth2AuthorizationRequestResolver接口.
@Bean
SecurityFilterChain customSecurityFilterChain(HttpSecurity http, ClientRegistrationRepository clientRegistrationRepository) throws Exception {
OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient = accessTokenResponseClient();
//TODO OAuth2Client test to be generatedcode_verifier,并使用 code_challenge_method 计算 code_challenge,And encapsulate it into the authorization request parameter,需要改造OAuth2AuthorizationRequestResolver接口.
DefaultOAuth2AuthorizationRequestResolver authorizationRequestResolver = new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository, OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI);
authorizationRequestResolver.setAuthorizationRequestCustomizer(builder -> builder.attributes(attributes -> {
if (!attributes.containsKey(PkceParameterNames.CODE_VERIFIER)) {
String codeVerifier = this.secureKeyGenerator.generateKey();
attributes.put(PkceParameterNames.CODE_VERIFIER, codeVerifier);
builder.additionalParameters(additionalParameters -> {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(codeVerifier.getBytes(StandardCharsets.US_ASCII));
String codeChallenge = Base64.getUrlEncoder().withoutPadding().encodeToString(digest);
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, codeChallenge);
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
} catch (NoSuchAlgorithmException ex) {
// plain 方式 This approach is almost obsolete
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, codeVerifier);
}
});
}
}));
http.authorizeRequests((requests) -> requests
.antMatchers("/test/bar", "/oauth2/jwks")
.hasAnyAuthority("ROLE_ANONYMOUS", "SCOPE_userinfo")
.anyRequest().authenticated())
//Then remodeledOAuth2AuthorizationRequestResolver配置到HttpSecurity: .oauth2Login().authorizationEndpoint().authorizationRequestResolver(authorizationRequestResolver)
.and()
// 获取token端点配置 比如根据code 获取 token
.tokenEndpoint().accessTokenResponseClient(accessTokenResponseClient);
http.oauth2Client()
.authorizationCodeGrant().authorizationRequestResolver(authorizationRequestResolver)
.accessTokenResponseClient(accessTokenResponseClient);
return http.build();
}
6.1、 Spring Authorization Server配置
Client configuration to be added .requireProofKey(true)
private RegisteredClient createJwtRegisteredClient(final String id) {
return RegisteredClient.withId(id)
// 客户端ID和密码
.clientId("testid")
// 名称 可不定义
.clientName("test")
// jwt Assertion Required
.clientAuthenticationMethod(ClientAuthenticationMethod.PRIVATE_KEY_JWT)
.clientSettings(ClientSettings.builder()
.tokenEndpointAuthenticationSigningAlgorithm(SignatureAlgorithm.RS256)
// 开启PKCE
.requireProofKey(true)
// private key jwt
.jwkSetUrl("http://localhost:8082/oauth2/jwks")
.build())
.build();
}
边栏推荐
- ABAP Data Types 和XSD Type 映射关系以及XSD Type属性
- Day37 LeetCode
- 【Unity入门计划】Collision2D类&Collider2D类
- 差分、前缀和模板
- 封装和使用通用的工具栏组件
- Ask next CDC mysql to Doris. Don't show the specific number of lines, how to do?
- Uni-app开发微信小程序使用本地图片做背景图
- C# 获取PCI等设备的插槽位置信息
- 大佬们,请问一下,oraclecdc报错没有序列化,可是我看源码中的确是没有继承序列化的,是什么原因
- StringUtils的具体操作
猜你喜欢
物联网时代下的网络整合推广外包精准化效果-深圳双赢世讯
J9数字论:Web3.0+互联网电商会引起怎样的火花?
Introduction to C integer data storage
day16--The use of the packet capture tool Charles
StringUtils的具体操作
【FAQ】【Push Kit】推送服务,回执配置一直报错、回执过期修改、怎么删除配置的回执
90.(cesium之家)cesium高度监听事件
The probability distribution and its application
二叉树 --- 堆
2022-08-01 网工进阶(二十四) STP进阶知识
随机推荐
J9数字论:关于DAO 特点的宏观分析
debezium-connector-mysql拉起docker报错:debezium启动docke
TensorFlow 2.9的零零碎碎(一)
爬虫-爬取某小说网站
iwemeta metaverse: a doll sells for 9999 yuan, and Bubble Mart thinks it is not expensive at all
【FAQ】【Push Kit】推送服务,回执配置一直报错、回执过期修改、怎么删除配置的回执
时序动作定位 | ASM-Loc:弱监督时序动作定位的动作感知片段建模(CVPR 2022)
placeholder 1
Spotify使用C4模型表达其架构设计
m.bjhjwy.com全面教学设备 类型包括: 教学仪器, 教学设备 ,
【Unity入门计划】制作RubyAdventure03-使用碰撞体&触发器实现世界交互
颜色选择器的使用
Introduction to the C language to realize bubble sort
2022-08-01 网工进阶(二十四) STP进阶知识
phpstudy starts automatically
Unity—UGUI控件
J9数字科普:Web 3.0 是关于数据所有权还是去中心化?
StringUtils的具体操作
Summary of ctfshow SSTI knowledge points
Uni applet Tencent map polygon background transparency