【OAuth 2.0】使用与更新
在 OAuth 2.0 授权流程中,令牌(Token) 是客户端访问资源服务器的凭证。访问令牌(Access Token)通常具有有效期,过期后无法继续使用,因此 OAuth 2.0 引入了刷新令牌(Refresh Token) 的机制,用于在访问令牌过期时,客户端可以请求新的访问令牌,而无需用户再次授权。这不仅增强了安全性,也提升了用户体验。
一、访问令牌(Access Token)
1. 访问令牌的作用
访问令牌是 OAuth 2.0 的核心,它用于代表用户授权客户端访问资源。令牌通常包含有权访问的资源范围(scope)以及有效期。客户端在访问资源服务器(如 API)时,必须携带有效的访问令牌,资源服务器会验证令牌的有效性,然后决定是否授予访问权限。
2. 令牌的使用
访问令牌通常通过 HTTP 请求头部发送到资源服务器:
GET /resource HTTP/1.1
Host: api.example.com
Authorization: Bearer
Authorization
头部的 Bearer
关键字表示令牌类型为 Bearer Token,即一个不记名的访问令牌,任何持有该令牌的人都可以访问授权的资源。
3. 令牌的有效期
为了防止访问令牌被滥用,访问令牌通常会有一个有效期。有效期可以根据应用场景进行配置。访问令牌过期后,客户端无法继续使用它进行授权访问。
例如,访问令牌可能在 1 小时后过期,之后必须使用刷新令牌来获取新的访问令牌。
二、刷新令牌(Refresh Token)
1. 刷新令牌的作用
刷新令牌是 OAuth 2.0 中用来获取新访问令牌的工具,主要用于单点登录的场景。它的主要作用是当访问令牌过期时,客户端可以通过刷新令牌来换取新的访问令牌,而不需要用户重新进行授权。刷新令牌的使用减少了用户的交互,提升了用户体验。
2. 刷新令牌的工作流程
当客户端获取到访问令牌和刷新令牌后,客户端可以在访问令牌过期时,通过调用授权服务器的令牌端点,使用刷新令牌换取新的访问令牌。
请求刷新访问令牌的流程:
- 客户端向授权服务器的
token
端点发送请求,并提供刷新令牌。 - 授权服务器验证刷新令牌的有效性,并返回一个新的访问令牌(有时会返回新的刷新令牌,但不一定)。
请求示例:
POST /oauth/token HTTP/1.1
Host: authorization-server.com
Content-Type: application/x-www-form-urlencodedgrant_type=refresh_token&refresh_token=&client_id=&client_secret=
在这个请求中,grant_type=refresh_token
指定这是一个基于刷新令牌的请求,授权服务器将验证刷新令牌的有效性,并返回新的访问令牌。
响应示例:
{
"access_token": "new_access_token",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "new_refresh_token"
}
3. 刷新令牌的有效期
刷新令牌通常比访问令牌的有效期更长,但它并非永久有效。授权服务器可能配置刷新令牌的过期时间,或者通过某些事件(如用户更改密码、用户撤销授权)导致刷新令牌失效。
三、访问令牌和刷新令牌的生命周期
- 访问令牌的生命周期
- 访问令牌的有效期通常比较短(例如几分钟或几小时),以防止因令牌泄露而导致的风险。
- 访问令牌在有效期内,客户端可以使用它访问受保护的资源。
- 刷新令牌的生命周期
- 刷新令牌的有效期通常较长(例如几天或几个月),但也可能配置为一次性使用。
- 当访问令牌过期时,客户端使用刷新令牌请求新的访问令牌。
- 如果刷新令牌过期,客户端需要重新走授权流程获取新的访问令牌和刷新令牌。
四、令牌的更新流程
当访问令牌过期后,客户端需要通过刷新令牌更新访问令牌的典型步骤如下:
- 客户端检测访问令牌是否过期:
- 客户端可以通过令牌的
expires_in
字段,或访问受保护资源时收到的错误消息(如 401 Unauthorized),检测到令牌已过期。
- 客户端使用刷新令牌请求新访问令牌:
- 客户端通过
refresh_token
请求新的访问令牌。
- 授权服务器返回新访问令牌:
- 授权服务器验证刷新令牌,如果刷新令牌有效,授权服务器返回一个新的访问令牌(有时也会返回一个新的刷新令牌)。
- 客户端继续使用新访问令牌访问资源:
- 客户端用新的访问令牌继续访问受保护资源。
五、令牌更新的安全性考虑
- 短有效期的访问令牌:
- 短期访问令牌能够减少令牌被盗后的安全风险,因为即便令牌被截获,攻击者只能在其有效期内使用。
- 安全存储刷新令牌:
- 刷新令牌的有效期较长,且可以获取新的访问令牌,因此需要更高的安全性。客户端应避免将刷新令牌存储在不安全的地方(如浏览器的 LocalStorage),以防止令牌泄露。
- 强制用户重新登录:
- 如果刷新令牌失效,客户端应引导用户重新进行登录授权,确保用户安全地获取新的令牌。
六、实际应用示例
假设一个应用程序使用 OAuth 2.0 授权码模式进行用户登录,并获取访问令牌和刷新令牌。客户端在用户登录后,保存访问令牌和刷新令牌以供后续使用。
// 登录成功后获取到访问令牌和刷新令牌
const accessToken = 'abc123';
const refreshToken = 'def456';// 当需要访问受保护资源时
function accessProtectedResource() {fetch('https://api.example.com/protected', {method: 'GET',headers: {'Authorization': `Bearer ${accessToken}`}}).then(response => {if (response.status === 401) {// 访问令牌过期,尝试用刷新令牌更新访问令牌refreshAccessToken();} else {// 处理成功的响应return response.json();}});
}// 使用刷新令牌更新访问令牌
function refreshAccessToken() {fetch('https://auth.example.com/oauth/token', {method: 'POST',headers: {'Content-Type': 'application/x-www-form-urlencoded'},body: new URLSearchParams({grant_type: 'refresh_token',refresh_token: refreshToken,client_id: 'client-id',client_secret: 'client-secret'})}).then(response => response.json()).then(data => {accessToken = data.access_token;// 保存新令牌,继续访问受保护资源accessProtectedResource();}).catch(error => {console.error('Refresh token failed', error);// 刷新令牌失效,引导用户重新登录});
}