sa-token-rust 0.1.14

A powerful Rust authentication and authorization framework
Documentation
# OAuth2 Authorization Code Flow Guide

[中文]./OAUTH2_GUIDE_zh-CN.md | English

---

## Overview

sa-token-rust implements the complete OAuth2 Authorization Code Grant flow, compliant with RFC 6749, supporting third-party application authorization, single sign-on, API access control, and more.

## Table of Contents

- [Features]#features
- [Quick Start]#quick-start
- [Core Components]#core-components
- [Authorization Flow]#authorization-flow
- [API Reference]#api-reference
- [Security Best Practices]#security-best-practices

## Features

- ✅ OAuth2 RFC 6749 compliant
- ✅ Authorization Code Grant flow
- ✅ Client management (registration, verification)
- ✅ Authorization code generation and validation
- ✅ Access token management
- ✅ Refresh token mechanism
- ✅ Strict redirect URI validation
- ✅ Scope permission control
- ✅ Token revocation
- ✅ Automatic expiration cleanup
- ✅ Enhanced error handling with detailed validation steps
- ✅ Comprehensive code documentation with security considerations
- ✅ Atomic code consumption (one-time use enforcement)

## Quick Start

### 1. Create OAuth2 Manager

```rust
use sa_token_core::OAuth2Manager;
use std::sync::Arc;

let storage = Arc::new(MemoryStorage::new());
let oauth2 = OAuth2Manager::new(storage)
    .with_ttl(
        600,      // Authorization code 10 minutes
        3600,     // Access token 1 hour
        2592000   // Refresh token 30 days
    );
```

### 2. Register Client

```rust
use sa_token_core::OAuth2Client;

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(),
    ],
    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?;
```

### 3. Complete Authorization Flow

```rust
// Step 1: Generate authorization code (after user consent)
let auth_code = oauth2.generate_authorization_code(
    "web_app_001".to_string(),
    "user_123".to_string(),
    "http://localhost:3000/callback".to_string(),
    vec!["read".to_string(), "profile".to_string()],
);

oauth2.store_authorization_code(&auth_code).await?;

// Step 2: Exchange code for token
let token = oauth2.exchange_code_for_token(
    &auth_code.code,
    "web_app_001",
    "secret_abc123xyz",
    "http://localhost:3000/callback",
).await?;

// Step 3: Use access token
let token_info = oauth2.verify_access_token(&token.access_token).await?;

// Step 4: Refresh token
let new_token = oauth2.refresh_access_token(
    token.refresh_token.as_ref().unwrap(),
    "web_app_001",
    "secret_abc123xyz",
).await?;
```

## Core Components

### OAuth2Manager

OAuth2 manager responsible for the entire authorization flow.

```rust
pub struct OAuth2Manager {
    storage: Arc<dyn SaStorage>,
    code_ttl: i64,
    token_ttl: i64,
    refresh_token_ttl: i64,
}
```

**Methods**:
- `new(storage)` - Create manager
- `with_ttl(code_ttl, token_ttl, refresh_ttl)` - Set expiration times
- `register_client(&client)` - Register client
- `get_client(client_id)` - Get client information
- `verify_client(client_id, client_secret)` - Verify client credentials
- `generate_authorization_code(...)` - Generate authorization code
- `store_authorization_code(&code)` - Store authorization code
- `exchange_code_for_token(...)` - Exchange code for token
- `verify_access_token(&token)` - Verify access token
- `refresh_access_token(...)` - Refresh access token
- `revoke_token(&token)` - Revoke token

### OAuth2Client

Client information.

```rust
pub struct OAuth2Client {
    pub client_id: String,
    pub client_secret: String,
    pub redirect_uris: Vec<String>,
    pub grant_types: Vec<String>,
    pub scope: Vec<String>,
}
```

### AuthorizationCode

Authorization code information.

```rust
pub struct AuthorizationCode {
    pub code: String,
    pub client_id: String,
    pub user_id: String,
    pub redirect_uri: String,
    pub scope: Vec<String>,
    pub created_at: DateTime<Utc>,
    pub expires_at: DateTime<Utc>,
}
```

### AccessToken

Access token response.

```rust
pub struct AccessToken {
    pub access_token: String,
    pub token_type: String,        // "Bearer"
    pub expires_in: i64,
    pub refresh_token: Option<String>,
    pub scope: Vec<String>,
}
```

## Authorization Flow

### Complete Flow Diagram

```
┌─────────┐                               ┌─────────────┐
│  User   │                               │   Client    │
└────┬────┘                               └──────┬──────┘
     │                                            │
     │  1. Access third-party app                 │
     │───────────────────────────────────────────▶│
     │                                            │
     │  2. Redirect to authorization page         │
     │◀───────────────────────────────────────────│
     │                                            │
┌────▼────┐                               ┌──────┴──────┐
│Auth     │                               │  Resource   │
│Server   │                               │  Server     │
└────┬────┘                               └──────┬──────┘
     │                                            │
     │  3. User grants permission                 │
     │                                            │
     │  4. Generate authorization code            │
     │  oauth2.generate_authorization_code()      │
     │                                            │
     │  5. Redirect back with code                │
     │───────────────────────────────────────────▶│
     │                                            │
     │  6. Exchange code for token                │
     │  oauth2.exchange_code_for_token()          │
     │◀───────────────────────────────────────────│
     │                                            │
     │  7. Return access & refresh tokens         │
     │───────────────────────────────────────────▶│
     │                                            │
     │  8. Access resources with token            │
     │                                            │───────▶
     │                                            │
     │  9. Return resources                       │
     │                                            │◀───────
     │                                            │
     │  10. Refresh token when expired            │
     │  oauth2.refresh_access_token()             │
     │◀───────────────────────────────────────────│
     │                                            │
     │  11. Return new access token               │
     │───────────────────────────────────────────▶│
     │                                            │
```

## API Reference

### Client Management

#### register_client

Register an OAuth2 client.

```rust
pub async fn register_client(&self, client: &OAuth2Client) -> SaTokenResult<()>
```

#### get_client

Get client information.

```rust
pub async fn get_client(&self, client_id: &str) -> SaTokenResult<OAuth2Client>
```

#### verify_client

Verify client credentials.

```rust
pub async fn verify_client(&self, client_id: &str, client_secret: &str) -> SaTokenResult<bool>
```

### Authorization Code Management

#### generate_authorization_code

Generate authorization code.

```rust
pub fn generate_authorization_code(
    &self,
    client_id: String,
    user_id: String,
    redirect_uri: String,
    scope: Vec<String>,
) -> AuthorizationCode
```

#### store_authorization_code

Store authorization code.

```rust
pub async fn store_authorization_code(&self, auth_code: &AuthorizationCode) -> SaTokenResult<()>
```

#### exchange_code_for_token

Exchange authorization code for access token.

```rust
pub async fn exchange_code_for_token(
    &self,
    code: &str,
    client_id: &str,
    client_secret: &str,
    redirect_uri: &str,
) -> SaTokenResult<AccessToken>
```

### Token Management

#### verify_access_token

Verify access token.

```rust
pub async fn verify_access_token(&self, access_token: &str) -> SaTokenResult<OAuth2TokenInfo>
```

#### refresh_access_token

Refresh access token.

```rust
pub async fn refresh_access_token(
    &self,
    refresh_token: &str,
    client_id: &str,
    client_secret: &str,
) -> SaTokenResult<AccessToken>
```

#### revoke_token

Revoke token.

```rust
pub async fn revoke_token(&self, token: &str) -> SaTokenResult<()>
```

## Security Best Practices

### 1. Client Credentials

- ✅ Use strong keys for client_secret (at least 32 characters)
- ✅ Rotate client keys regularly
- ✅ Store credentials securely, never hardcode
- ✅ Use HTTPS to transmit credentials

### 2. Authorization Code

- ✅ Code can only be used once (implemented)
- ✅ Short validity period (default 10 minutes)
- ✅ Strict redirect_uri validation (implemented)
- ✅ Use state parameter to prevent CSRF

### 3. Access Token

- ✅ Short validity period (recommended 1-2 hours)
- ✅ Use Bearer Token format
- ✅ Validate signature and expiration
- ✅ Implement token revocation (implemented)

### 4. Transmission Security

- **Must use HTTPS**
- ✅ Enable HSTS
- ✅ Use secure TLS versions (1.2+)
- ✅ Verify SSL certificates

## Examples

Run the complete example:

```bash
cargo run --example oauth2_example
```

View example code: `examples/oauth2_example.rs`

## References

- [OAuth 2.0 RFC 6749]https://tools.ietf.org/html/rfc6749
- [OAuth 2.0 Security Best Practices]https://tools.ietf.org/html/draft-ietf-oauth-security-topics
- [Example Code]../examples/oauth2_example.rs

## Next Steps

- [JWT Guide]./JWT_GUIDE.md
- [Event Listeners]./EVENT_LISTENER.md
- [Permission Matching]./PermissionMatching.md