use std::sync::Arc;
use sa_token_core::{OAuth2Manager, OAuth2Client};
use sa_token_storage_memory::MemoryStorage;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("========================================");
println!("OAuth2 授权码模式示例 | OAuth2 Authorization Code Flow Example");
println!("========================================\n");
let storage = Arc::new(MemoryStorage::new());
let oauth2 = OAuth2Manager::new(storage)
.with_ttl(600, 3600, 2592000);
println!(">>> 步骤 1: 注册 OAuth2 客户端 | Step 1: Register OAuth2 Client\n");
let client = OAuth2Client {
client_id: "web_app_001".to_string(),
client_secret: "secret_abc123xyz".to_string(),
redirect_uris: vec![
"http://localhost:3000/callback".to_string(),
"http://localhost:3000/auth/callback".to_string(),
],
grant_types: vec![
"authorization_code".to_string(),
"refresh_token".to_string(),
],
scope: vec![
"read".to_string(),
"write".to_string(),
"profile".to_string(),
],
};
oauth2.register_client(&client).await?;
println!("客户端信息:");
println!(" Client ID: {}", client.client_id);
println!(" Client Secret: {}", client.client_secret);
println!(" Redirect URIs: {:?}", client.redirect_uris);
println!(" Grant Types: {:?}", client.grant_types);
println!(" Scopes: {:?}\n", client.scope);
println!(">>> 步骤 2: 用户授权 - 生成授权码\n");
let user_id = "user_10086";
let redirect_uri = "http://localhost:3000/callback";
let requested_scope = vec!["read".to_string(), "profile".to_string()];
if !oauth2.validate_redirect_uri(&client, redirect_uri) {
return Err("Invalid redirect URI".into());
}
if !oauth2.validate_scope(&client, &requested_scope) {
return Err("Invalid scope".into());
}
let auth_code = oauth2.generate_authorization_code(
client.client_id.clone(),
user_id.to_string(),
redirect_uri.to_string(),
requested_scope.clone(),
);
println!("授权码信息:");
println!(" Code: {}", auth_code.code);
println!(" User ID: {}", auth_code.user_id);
println!(" Client ID: {}", auth_code.client_id);
println!(" Redirect URI: {}", auth_code.redirect_uri);
println!(" Scope: {:?}", auth_code.scope);
println!(" Expires At: {}\n", auth_code.expires_at);
oauth2.store_authorization_code(&auth_code).await?;
println!("✓ 授权码已存储\n");
println!(">>> 步骤 3: 用授权码换取访问令牌\n");
let access_token = oauth2.exchange_code_for_token(
&auth_code.code,
&client.client_id,
&client.client_secret,
redirect_uri,
).await?;
println!("访问令牌:");
println!(" Access Token: {}", access_token.access_token);
println!(" Token Type: {}", access_token.token_type);
println!(" Expires In: {} 秒", access_token.expires_in);
println!(" Refresh Token: {}", access_token.refresh_token.as_ref().unwrap());
println!(" Scope: {:?}\n", access_token.scope);
println!(">>> 步骤 4: 验证访问令牌\n");
let token_info = oauth2.verify_access_token(&access_token.access_token).await?;
println!("令牌信息:");
println!(" User ID: {}", token_info.user_id);
println!(" Client ID: {}", token_info.client_id);
println!(" Scope: {:?}", token_info.scope);
println!(" Expires At: {}\n", token_info.expires_at);
println!(">>> 步骤 5: 使用刷新令牌获取新的访问令牌\n");
let refresh_token = access_token.refresh_token.as_ref().unwrap();
let new_access_token = oauth2.refresh_access_token(
refresh_token,
&client.client_id,
&client.client_secret,
).await?;
println!("新访问令牌:");
println!(" Access Token: {}", new_access_token.access_token);
println!(" Token Type: {}", new_access_token.token_type);
println!(" Expires In: {} 秒", new_access_token.expires_in);
println!(" Refresh Token: {}\n", new_access_token.refresh_token.as_ref().unwrap());
println!(">>> 步骤 6: 撤销令牌\n");
oauth2.revoke_token(&new_access_token.access_token).await?;
println!("✓ 令牌已撤销\n");
match oauth2.verify_access_token(&new_access_token.access_token).await {
Ok(_) => println!("✗ 令牌仍然有效(不应该)"),
Err(_) => println!("✓ 令牌已失效(预期结果)\n"),
}
println!("========================================");
println!("OAuth2 授权流程完成");
println!("========================================\n");
println!("完整流程:");
println!(" 1. 注册客户端 ✓");
println!(" 2. 生成授权码 ✓");
println!(" 3. 授权码换令牌 ✓");
println!(" 4. 验证访问令牌 ✓");
println!(" 5. 刷新访问令牌 ✓");
println!(" 6. 撤销令牌 ✓");
Ok(())
}