PKCE 在 OIDC 中如何保护客户端免受第三方拦截

文摘   2024-08-20 10:59   浙江  

在 OIDC 的登录过程中,我们一般采用授权码模式的方式获取 Access Token,其中最重要的一步是验证之后通过 Authorization code 换取 Access Token,那么我们在整个登录过程中是如何保证 Authorization code 不被窃取的呢?


OIDC 中的 Client 类型


Auth 2.0 中将 client 分为两类:


  • Confidential Clients 机密型应用:能够安全的存储凭证(client_secret),例如后端服务,可以理解为机密性应用,因为你的后端能够安全的保存 client_secret,而不会将其直接暴露给用户,此时你可以使用授权码模式。

  • Public Clients 公共客户端:无法安全存储凭证(client secrets),例如Windows 应用程序、移动端,或者完全前后端分离的应用,应当使用 Authorization code + PKCE 模式。


授权码模式

Authorization Code Grand



在OIDC中,我们通常使用授权码模式 Authorization code grand,其流程如上图:


  1. client 向 user agent 发起验证请求;

  2. user agent 向 authorization server 发起验证请求;

  3. 验证成功后 authorization server 把 authorization code 返回给 user agent;

  4. user agent 将 authorization code 返回给 client;

  5. client 将 authorization code 发送给 authorization server;

  6. authorization server 根据 redirect url 将 access token 返回给 client。


在上述步骤中,user agent 与 authorization server之间和 client 与 authorization server 之间的通信都受 TLS 的保护,所以我们认为这些步骤都是安全的。


Authorization code 在第(4)步中有可能被截获。


Confidential Clients 如何利用

client_secret 保证安全



confidential client 在第(5)步把 authorization code 发送给authorization server的时候把client_secret放在request header 里, authorization server 验证 request header 里的 client_secret 就可以信任这个发送请求的 client 了。


Public Clients 的中间人攻击


OAuth 2.0的public clients容易受到 Authorization code 拦截攻击的影响。


Authorization server 在步骤(3)中返回 authorization code。在步骤(4)中,authorization code 通过步骤(1)中提供的 redirect url 返回给请求者。


恶意应用程序有可能注册自身作为自定义方案的处理程序,除了合法的 OAuth 2.0 应用程序。一旦注册成功,恶意应用程序就能在步骤(4)中拦截授权码。这使得攻击者可以分别在步骤(5)和(6)中请求并获取 access token。



PKCE 如何保障 Public Clients

避免中间人攻击



PKCE: Proof Key for Code Exchange


为了减轻这种攻击,PKCE 利用一个动态创建的加密随机密钥,称为 code verifier。每个授权请求都会创建一个唯一的代码验证器,并将其转换后的值,称为 code challenge,发送到授权服务器以获 authorization code。获取的 authorization code 随后与 code verifier 一起发送到 token endpoint,服务器会将其与先前接收的请求代码进行比较,以验证客户端对 code verifier 的拥有权。这种方法有效地减轻了攻击风险,因为攻击者无法获知这个一次性密钥,它通过 TLS 传输,无法被拦截。



A. client 创建并记录一个 code_verifier,并且用一个转换方法 t_m(transformation_method) 将这个 code_verifier生成一个 t(code_verifier)(称为code_challenge),将其与转换方法 (transformation method)t_m 一起发送到 OAuth 2.0授权请求中。


B. authorization endpoint 像往常一样响应,但记录下 code_challenge 和转换方法 t_m(transformation method)。


C.client 在请求 access token 时,如往常一样发送 authorization code,但包括在步骤 A 生成的 code_verifier。


D. authorization server 用之前记录的 t_m 和收到的 code_verifier 生成 t_m(code_verifier),并与步骤 B 中记录的 code_challenge 进行比较。如果它们不一致,则拒绝访问。


攻击者如果在步骤 B 拦截了 authorization code,则无法使用它兑换 access token,因为他们没法获取 code_verifier。


上述步骤 B 中 authorization endpoint 也可以不用把 code_challenge 和 t_m(transformation method) 记录下来,而是如下图所示通过加加密之后放在 respone 中由 client 再传回来,这也是 authorization server 通常的做法。



参考文献:

  • https://openid.net/specs/openid-connect-core-1_0.html

  • https://datatracker.ietf.org/doc/html/rfc6749#page-4

  • https://datatracker.ietf.org/doc/html/rfc6750

  • https://datatracker.ietf.org/doc/html/rfc7636


微策略 商业智能
微策略 MicroStrategy (Nasdaq: MSTR) 是企业级分析和移动应用软件行业的佼佼者。关注我们了解行业资讯、技术干货和程序员日常。
 最新文章