OAuth 2.0 授权框架详解
OAuth 2.0 是一个授权框架,允许应用程序在 HTTP 服务(如 Facebook、GitHub 或 Azure Active Directory)上获得对用户帐户的有限访问权限。本文将探讨标准授权码授予类型、其增强变体 PKCE 以及其他相关的授权类型。
一. 标准授权码授予类型
标准授权码授予类型适用于服务器端应用程序,在这种类型的应用程序中,客户端的密钥可以安全存储。这种流程确保访问令牌不会暴露给用户的浏览器,使其成为一种安全的 Web 应用程序选项。
1.1 流程步骤
-
用户发起认证请求: 用户尝试通过客户端应用程序访问受保护的资源。客户端应用程序将用户重定向到授权服务器,并发出授权请求。
用户 → 客户端应用程序 → 授权服务器
-
用户认证和同意: 用户登录到授权服务器并同意客户端请求的权限。
用户登录 → 授权服务器
-
发放授权码: 授权服务器将用户重定向回客户端应用程序,并附上授权码。
授权服务器 → 客户端应用程序(包含授权码)
-
令牌交换: 客户端应用程序在令牌端点用授权码交换访问令牌和可选的刷新令牌。
// 示例代码:使用授权码交换访问令牌
var tokenResponse = await client.PostAsync("https://authorization-server/token", new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("code", authorizationCode),
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("redirect_uri", "https://client-app/callback"),
new KeyValuePair<string, string>("client_id", "your-client-id"),
new KeyValuePair<string, string>("client_secret", "your-client-secret")
}));
1.2 示例用例
-
Web 应用程序:具有服务器端逻辑且可以安全存储客户端密钥的应用程序。
二. 带 PKCE 的授权码授予类型(Proof Key for Code Exchange)
PKCE(发音为 "pixy")增强了标准授权码流程的安全性。它适用于公开客户端,例如无法安全存储客户端密钥的移动应用程序和单页面应用程序(SPA)。
2.1 流程步骤
-
生成代码验证器和挑战: 客户端生成一个代码验证器和一个代码挑战。
// 示例代码:生成代码验证器和挑战
var codeVerifier = GenerateRandomString();
var codeChallenge = ComputeCodeChallenge(codeVerifier); -
授权请求: 客户端发送带有代码挑战的授权请求。
客户端应用程序 → 授权服务器(包含代码挑战)
-
用户认证和同意: 用户在授权服务器上进行身份验证并同意权限。
-
发放授权码: 授权服务器返回授权码。
-
使用验证器交换令牌: 客户端通过提供代码验证器交换访问令牌。
// 示例代码:使用代码验证器交换访问令牌
var tokenResponse = await client.PostAsync("https://authorization-server/token", new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("code", authorizationCode),
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("redirect_uri", "https://client-app/callback"),
new KeyValuePair<string, string>("client_id", "your-client-id"),
new KeyValuePair<string, string>("code_verifier", codeVerifier)
}));
2.2 示例用例
-
移动和单页面应用程序:客户端密钥无法安全存储的应用程序。
三. 设备授权授予类型
设备授权授予类型用于没有浏览器或输入能力的设备,例如智能电视或 IoT 设备。
3.1 流程步骤
-
设备代码请求: 设备向授权服务器请求设备代码和用户代码。
设备 → 授权服务器(请求设备代码)
-
用户代码显示: 设备显示用户代码,并指示用户访问一个 URL 并输入代码。
-
用户认证和授权: 用户在其他设备上进行身份验证并输入用户代码。
-
轮询授权: 设备轮询授权服务器以获取访问令牌。
// 示例代码:轮询获取访问令牌
var tokenResponse = await client.PostAsync("https://authorization-server/device/token", new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("device_code", deviceCode),
new KeyValuePair<string, string>("grant_type", "urn:ietf:params:oauth:grant-type:device_code")
})); -
发放访问令牌: 一旦用户授权,设备将收到访问令牌。
3.2 示例用例
-
智能电视和 IoT 设备:输入能力有限的设备。
四. 客户端凭证授予类型
客户端凭证授予类型用于客户端根据自身凭证而非用户身份请求访问资源服务器。这通常用于机器对机器(M2M)通信。
4.1 流程步骤
-
令牌请求: 客户端应用程序通过提供客户端凭证(客户端 ID 和密钥)向授权服务器请求访问令牌。
// 示例代码:请求访问令牌
var tokenResponse = await client.PostAsync("https://authorization-server/token", new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials"),
new KeyValuePair<string, string>("client_id", "your-client-id"),
new KeyValuePair<string, string>("client_secret", "your-client-secret")
})); -
发放访问令牌: 授权服务器响应访问令牌。
4.2 示例用例
-
服务帐户:访问 API 的后端服务或应用程序。
五. 资源所有者密码凭证授予类型
资源所有者密码凭证授予类型涉及用户直接向客户端应用程序提供用户名和密码。这种授予类型较少安全,应该仅在客户端高度可信的情况下使用。
5.1 流程步骤
-
令牌请求: 客户端应用程序通过提供用户凭证(用户名和密码)及其客户端凭证向授权服务器请求访问令牌。
// 示例代码:使用用户名和密码请求访问令牌
var tokenResponse = await client.PostAsync("https://authorization-server/token", new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", "user@example.com"),
new KeyValuePair<string, string>("password", "user-password"),
new KeyValuePair<string, string>("client_id", "your-client-id"),
new KeyValuePair<string, string>("client_secret", "your-client-secret")
})); -
发放访问令牌: 授权服务器响应访问令牌。
5.2 示例用例
-
遗留应用程序:高度信任的应用程序直接管理用户凭证。
六. 隐式授予类型
隐式授予类型适用于公开客户端,例如无法安全存储客户端密钥的单页面应用程序。它直接发放访问令牌,无需进行授权码交换。
6.1 流程步骤
-
授权请求: 客户端应用程序将用户引导到授权服务器,授权请求中指定响应类型为令牌。
客户端应用程序 → 授权服务器(请求令牌)
-
用户认证和同意: 用户在授权服务器上进行身份验证并同意权限。
-
发放访问令牌: 授权服务器将用户重定向回客户端应用程序,并在 URL 片段中包含访问令牌。
授权服务器 → 客户端应用程序(包含访问令牌的 URL 片段)
6.2 示例用例
-
单页面应用程序:没有后端服务器的应用程序。
七. 结论
OAuth 2.0 框架提供了多种授予类型,以满足不同的应用场景和安全需求。标准授权码授予类型,特别是使用 PKCE 增强的授权码授予类型,由于其安全特性被广泛使用。其他授予类型,如设备授权、客户端凭证和资源所有者密码凭证,满足特定用例,使 OAuth 2.0 成为一个灵活而
全面的框架,用于管理各种应用程序的授权。
通过理解和选择适当的 OAuth 2.0 授予类型,开发人员可以确保安全和高效地访问受保护的资源,提升应用程序的整体安全性和用户体验。