从 sgcWebSockets 2024.5.0 起,支持 PKCE(代码交换证明密钥,Proof of Key Code Exchange),这是 OAuth 2.0 协议的扩展,有助于防止代码拦截攻击。
什么是 PKCE
PKCE(代码交换证明密钥)是 OAuth 2.0 的安全增强机制,旨在防止公共或原生应用程序中的授权码拦截攻击。它在 RFC 7636 中有详细说明,作为缓解"授权码拦截"漏洞的技术,特别适用于无法可靠保密客户端密钥的环境,例如移动或客户端应用程序。
在典型的 OAuth 2.0 授权码授权流程中,客户端应用程序通过将用户重定向到授权服务器来获取授权码,然后用该码换取访问令牌。但是,如果攻击者拦截了授权码,他们可能会利用它来获取访问令牌并访问受保护的资源。
PKCE 通过引入证明密钥机制来解决此风险。PKCE 的关键组成部分是:
- 代码验证器(Code Verifier):由客户端应用程序在 OAuth 流程开始时生成的随机高熵字符串。验证器必须至少 43 个字符、最多 128 个字符,使用非保留字符(A-Z、a-z、0-9、"-"、"."、"_"、"~")。
- 代码挑战(Code Challenge):代码验证器的衍生版本,使用转换方法创建。转换方法通常为"S256"(表示 SHA-256 哈希),也可以是"plain"(代码挑战与代码验证器相同)。
PKCE 流程如下所示:
- 客户端应用程序生成代码验证器,并从中派生代码挑战。
- 客户端应用程序发起 OAuth 授权请求,包含代码挑战和代码挑战方法(plain 或 S256)。
- 用户授予访问权限后,授权服务器将授权码发送给客户端。
- 客户端应用程序将授权码发送到令牌端点以换取访问令牌时,同时包含代码验证器。
- 授权服务器通过应用与创建代码挑战时相同的转换方法来验证代码验证器,并检查其是否与存储的代码挑战匹配。
- 如果验证成功,授权服务器颁发访问令牌;否则,请求将被拒绝。
此机制确保只有拥有原始代码验证器的客户端才能成功将授权码换取访问令牌,在 OAuth 流程中提供了强大的安全保障。
Delphi OAuth2 客户端
TsgcHTTP_OAuth2_Client 组件支持授权码 + PKCE 流程,要使用此授权类型,请将 GrantType 属性设置为 auth2CodePKCE。
oAuth2 := TsgcHTTP2_OAuth2.Create(nil);
oAuth2.LocalServerOptions.Host := '127.0.0.1';
oAuth2.LocalServerOptions.Port := 8080;
oAuth2.AuthorizationServerOptions.AuthURL := 'https://accounts.google.com/o/oauth2/auth';
oAuth2.AuthorizationServerOptions.TokenURL := 'https://accounts.google.com/o/oauth2/token';
oAuth2.AuthorizationServerOptions.Scope.Add('https://mail.google.com/');
oAuth2.OAuth2Options.ClientId := '180803918357-eqjtn20gqfhcs6gjkebbrrenh022mqqc.apps.googleusercontent.com';
oAuth2.OAuth2Options.ClientSecret := '_by0iYYrvVHxC2Z8TbtNEYQN';
oAuth2.OAuth2Options.GrantType := auth2CodePKCE;
procedure OnOAuth2AfterAccessToken(Sender: TObject; const Access_Token, Token_Type, Expires_In,
Refresh_Token, Scope, RawParams: string; var Handled: Boolean);
begin
<...>
<...>
end;
oAuth2.OnAfterAccessToken := OnOAuth2AfterAccessToken;
oAuth2.Start;
Delphi OAuth2 服务器
TsgcHTTP_OAuth2_Server 组件默认支持 PKCE(尽管可以在 OAuth2Options.PKCE 属性中禁用)。当服务器检测到 OAuth2 客户端正在使用 PKCE 时,将验证 PKCE 值是否有效,若无效则在响应中返回错误。
以下是关于如何使用 Delphi OAuth2 服务器的链接:
