同步操作将从 heguangchuan/spring-authorization-server 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
原文来自 : https://zhuanlan.zhihu.com/p/433472843
PKCE 全称是 Proof Key for Code Exchange, 它是 OAuth 2.0 核心的一个扩展协议, 所以可以和现有的授权模式结合使用,PKCE 最初是为移动设备应用和本地应用创建的, 主要是为了减少公共客户端的授权码拦截攻击。
PKCE 协议本身是对 OAuth 2.0 的扩展, 它和之前的授权码流程大体上是一致的, 区别在于, 在向授权服务器的 authorize endpoint 请求时,需要额外的 code_challenge 和 code_challenge_method 参数, 向 token endpoint 请求时, 需要额外的 code_verifier 参数, 最后授权服务器会对这三个参数进行对比验证, 通过后颁发令牌。
在 OAuth 2.0 授权码模式(Authorization Code)中, 客户端通过授权码code向授权服务器获取访问令牌(access_token) 时,同时还需要在请求中携带客户端密钥(client_secret), 授权服务器对其进行验证, 保证 access_token 颁发给了合法的客户端, 对于公开的客户端来说, 本身就有密钥泄露的风险, 所以就不能使用常规 OAuth 2.0 的授权码模式。在经过一段时间之后, PKCE 扩展协议推出, 就是为了解决公开客户端的授权安全问题。
上面是OAuth 2.0 授权码模式的完整流程, 授权码拦截攻击就是图中的C步骤发生的, 也就是授权服务器返回给客户端授权码的时候, 这么多步骤中为什么 C 步骤是不安全的呢? 在 OAuth 2.0 核心规范中, 要求授权服务器的 anthorize endpoint 和 token endpoint 必须使用 TLS(安全传输层协议)保护, 但是授权服务器携带授权码code返回到客户端的回调地址时, 有可能不受TLS 的保护, 恶意程序就可以在这个过程中拦截授权码code, 拿到 code 之后, 接下来就是通过 code 向授权服务器换取访问令牌 access_token , 对于机密的客户端来说, 请求 access_token 时需要携带客户端的密钥 client_secret , 而密钥保存在后端服务器上, 所以恶意程序通过拦截拿到授权码code 也没有用, 而对于公开的客户端(手机App, 桌面应用)来说, 本身没有能力保护 client_secret, 因为可以通过反编译等手段, 拿到客户端 client_secret, 也就可以通过授权码 code 换取 access_token, 到这一步,恶意应用就可以拿着 token 请求资源服务器了。
state 参数, 在 OAuth 2.0 核心协议中, 通过 code 换取 token 步骤中, 推荐使用 state 参数, 把请求和响应关联起来, 可以防止跨站点请求伪造-CSRF攻击, 但是 state 并不能防止上面的授权码拦截攻击,因为请求和响应并没有被伪造, 而是响应的授权码被恶意程序拦截。
KCE 协议本身是对 OAuth 2.0 的扩展, 它和之前的授权码流程大体上是一致的, 区别在于, 在向授权服务器的 authorize endpoint 请求时,需要额外的 code_challenge 和 code_challenge_method 参数, 向 token endpoint 请求时, 需要额外的 code_verifier 参数, 最后授权服务器会对这三个参数进行对比验证, 通过后颁发令牌。
对于每一个OAuth 授权请求, 客户端会先创建一个代码验证器 code_verifier, 这是一个高熵加密的随机字符串, 使用URI 非保留字符 ( Unreserved characters), 范围 [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~", 因为非保留字符在传递时不需要进行 URL 编码, 并且 code_verifier 的长度最小是 43, 最大是 128, code_verifier 要具有足够的熵它是难以猜测的。
简单点说就是在 [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~" 范围内,生成43-128位的随机字符串。
对 code_verifier 进行转换的方法, 这个参数会传给授权服务器, 并且授权服务器会记住这个参数, 颁发令牌的时候进行对比, 若一致则颁发令牌。
使用 code_challenge_method 对 code_verifier 进行转换得到 code_challenge
上面我们说了授权码拦截攻击, 它是指在整个授权流程中, 只需要拦截到从授权服务器回调给客户端的授权码 code, 就可以去授权服务器申请令牌了, 因为客户端是公开的, 就算有密钥 client_secret 也是形同虚设, 恶意程序拿到访问令牌后, 就可以光明正大的请求资源服务器了。
PKCE 是怎么做的呢? 既然固定的 client_secret 是不安全的, 那就每次请求生成一个随机的密钥(code_verifier), 第一次请求到授权服务器的 authorize endpoint时, 携带 code_challenge 和 code_challenge_method, 也就是 code_verifier 转换后的值和转换方法, 然后授权服务器需要把这两个参数缓存起来, 第二次请求到 token endpoint 时, 携带生成的随机密钥的原始值 (code_verifier) , 然后授权服务器进行验证,通过后才颁发令牌, 那向授权服务器 authorize endpoint 和 token endpoint 发起的这两次请求,该如何关联起来呢? 通过 授权码 code 即可, 所以就算恶意程序拦截到了授权码 code, 但是没有 code_verifier, 也是不能获取访问令牌的,最后看一下请求参数的示例:
GET /oauth2/authorize
https://www.authorization-server.com/oauth2/authorize?
response_type=code
&client_id=s6BhdRkqt3
&scope=user
&state=8b815ab1d177f5c8e
&redirect_uri=https://www.client.com/callback
&code_challenge_method=S256
&code_challenge=FWOeBX6Qw_krhUE2M0lOIH3jcxaZzfs5J4jtai5hOX4
POST /oauth2/token
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
https://www.authorization-server.com/oauth2/token?
grant_type=authorization_code
&code=d8c2afe6ecca004eb4bd7024
&redirect_uri=https://www.client.com/callback
&code_verifier=2D9RWc5iTdtejle7GTMzQ9Mg15InNmqk3GZL-Hg5Iz0
https://tonyxu-io.github.io/pkce-generator/
需要添加一个公共客户端并且设置proof key支持,需要准备好的 code_verifier 和 code challenge,可以使用上面的网站生成
RegisteredClient pkce=RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("pkce-client")
.clientSecret("{noop}pkce-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.redirectUri("https://www.baidu.com")
.scope(OidcScopes.OPENID)
.scope(OidcScopes.PROFILE)
.scope("message.read")
//设置客户端 使用 proofKey
.clientSettings(ClientSettings.builder().requireProofKey(true).build())
.build();
http://127.0.0.1:9000/oauth2/authorize?client_id=pkce-client&response_type=code&scope=message.read openid&redirect_uri=https://www.baidu.com&code_challenge=fkvR4xhVr4wjnXV1DiFyyiHZZUeeC-WdYmfZ7AlRWP0&code_challenge_method=S256
授权服务器将引导用户至登录界面进行登录,在配置文件中配置了 abc/abc 用户,登录即可,登录后授权服务器将直接重定向到 百度 ,并带上code
https://www.baidu.com/?code=_G2leudiM9ceC3aIXfXHJFnvPj0vNL8XYtLBuCHF_LHENXZ9Bqpl1S5ThG3Fj2lqCt0BLOhkTYvqHPClFiV_l-KOep2Ho8JCLVhxrQ13VmeJY4qYFZB9L3nNX58IOPmv
使用上面授权服务器重定向时的 code 参数访问 access token
curl --location --request POST 'localhost:9000/oauth2/token?grant_type=authorization_code&redirect_uri=https://www.baidu.com&code=0o2dyZifIIx81tGRRGII5bYUfWRv4jmmNoCoA-rt6VZidfZgg8_jTtN-SOhvZ-9uofNHYT1khtCTRInDJdMSCH9JiHRqSLkE7HBwORVBWUJve-sKCtlSE8iTTigNoN18&client_id=pkce-client&code_verifier=jzrdwRz_F58fqet3SzEDX_gnFeJbDAo3uEyGm_UFtKE'
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。