### ============================================
### OAuth2 示例请求集合(按顺序执行)
### 适配:Spring Boot OAuth2 Demo (localhost:9000)
### ============================================
@host = http://localhost:9000
@machineClientId = demo-client-machine
@machineClientSecret = machine-secret
@authCodeClientId = demo-client-auth-code
@authCodeClientSecret = demo-secret
@redirectUri = http://localhost:9000/oauth2/callback
### 0) 健康检查(服务是否已启动)
GET {{host}}/health
### 1) 获取 JWKS(查看 JWT 公钥)
GET {{host}}/oauth2/jwks
### 2) 客户端凭证模式:获取 access_token
POST {{host}}/oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ZGVtby1jbGllbnQtbWFjaGluZTptYWNoaW5lLXNlY3JldA==
grant_type=client_credentials&scope=message.read message.write
> {%
client.test("Client Credentials 获取成功", function () {
client.assert(response.status === 200, "HTTP 状态码不是 200");
client.assert(!!response.body.access_token, "access_token 为空");
});
client.global.set("access_token", response.body.access_token);
%}
### 3) 使用 access_token 访问 /api/me(查看当前认证主体和 claims)
GET {{host}}/api/me
Authorization: Bearer {{access_token}}
### 4) 读接口(需要 scope: message.read)
GET {{host}}/api/messages/read
Authorization: Bearer {{access_token}}
### 5) 写接口(需要 scope: message.write)
POST {{host}}/api/messages/write
Authorization: Bearer {{access_token}}
### 6) 错误示例:不带 token 访问受保护接口(应返回 401)
GET {{host}}/api/messages/read
### 7) 令牌自省(查看 token 是否 active)
POST {{host}}/oauth2/introspect
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ZGVtby1jbGllbnQtbWFjaGluZTptYWNoaW5lLXNlY3JldA==
token={{access_token}}
### 8) 撤销令牌(revoke)
POST {{host}}/oauth2/revoke
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ZGVtby1jbGllbnQtbWFjaGluZTptYWNoaW5lLXNlY3JldA==
token={{access_token}}
### 9) 撤销后再次调用(通常应失败:401)
GET {{host}}/api/messages/read
Authorization: Bearer {{access_token}}
### ----------------------------------------------------------------
### 10) 授权码模式(手动步骤)
### 第一步:浏览器打开下面 URL 登录并授权,拿到 code 后粘贴到 @authCode 变量
{{host}}/oauth2/authorize?response_type=code&client_id={{authCodeClientId}}&scope=message.read%20message.write&redirect_uri={{redirectUri}}
### ----------------------------------------------------------------
@authCode = VwATVSbY6pdJvQ5nkfcLMaUBi3Rjbs-h7-ihu_WK1c1zdkBk6yiP9U0hJSTjplIVh65zOHajXVg7A2FxauNqQW5461YR8eDBeiExHcyCMbw9-53DE66MJXl8qwtVQSWM
### 11) 授权码换取 access_token + refresh_token
POST {{host}}/oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ZGVtby1jbGllbnQtYXV0aC1jb2RlOmRlbW8tc2VjcmV0
grant_type=authorization_code&code={{authCode}}&redirect_uri={{redirectUri}}
> {%
client.test("Authorization Code 换 token 成功", function () {
client.assert(response.status === 200, "HTTP 状态码不是 200");
client.assert(!!response.body.access_token, "access_token 为空");
client.assert(!!response.body.refresh_token, "refresh_token 为空");
});
client.global.set("auth_code_access_token", response.body.access_token);
client.global.set("refresh_token", response.body.refresh_token);
%}
### 12) 刷新令牌(refresh_token -> 新 access_token)
POST {{host}}/oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ZGVtby1jbGllbnQtYXV0aC1jb2RlOmRlbW8tc2VjcmV0
grant_type=refresh_token&refresh_token={{refresh_token}}
> {%
client.test("Refresh Token 刷新成功", function () {
client.assert(response.status === 200, "HTTP 状态码不是 200");
client.assert(!!response.body.access_token, "新的 access_token 为空");
});
client.global.set("refreshed_access_token", response.body.access_token);
%}
### 13) 用刷新后的 token 访问受保护接口
GET {{host}}/api/messages/read
Authorization: Bearer {{refreshed_access_token}}