Add SelfFreezoneClient wrapper for Self components
- Created SelfFreezoneClient in Self components
- Wraps SDK FreezoneScriptClient for Self-specific operations
- Implements send_verification_email method
- Uses Rhai script template for email verification
- Includes template variable substitution
- Added serde-wasm-bindgen dependency
Usage:
let client = SelfFreezoneClient::builder()
.supervisor_url("http://localhost:8080")
.secret("my-secret")
.build()?;
client.send_verification_email(
"user@example.com",
"123456",
"https://verify.com/abc"
).await?;
This commit is contained in:
299
docs/authentication-flows.md
Normal file
299
docs/authentication-flows.md
Normal file
@@ -0,0 +1,299 @@
|
||||
# Authentication Flows
|
||||
|
||||
## Overview
|
||||
|
||||
Self implements a cryptographic challenge-response authentication system that eliminates the need for passwords while providing strong security guarantees. The system supports both new user registration and existing user authentication flows.
|
||||
|
||||
## Registration Flow
|
||||
|
||||
### Step-by-Step Process
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as User
|
||||
participant C as Client (Browser)
|
||||
participant S as Server
|
||||
participant E as Email System
|
||||
|
||||
Note over U,E: Phase 1: Email Verification
|
||||
U->>C: Enter name and email
|
||||
C->>S: POST /api/send-verification
|
||||
S->>E: Generate verification link
|
||||
S->>C: Verification sent response
|
||||
S-->>U: Display verification link (dev mode)
|
||||
|
||||
Note over U,E: Phase 2: Email Confirmation
|
||||
U->>S: Click verification link
|
||||
S->>S: Mark email as verified
|
||||
S->>C: SSE notification (verified)
|
||||
C->>C: Update UI to show verified status
|
||||
|
||||
Note over U,E: Phase 3: Key Generation
|
||||
U->>C: Click "Generate Keys"
|
||||
C->>C: Generate secp256k1 key pair
|
||||
C->>C: Display private key for backup
|
||||
U->>C: Copy private key (mandatory)
|
||||
U->>C: Enter encryption password
|
||||
C->>C: Encrypt private key with AES-256-GCM
|
||||
C->>C: Store encrypted key in localStorage
|
||||
|
||||
Note over U,E: Phase 4: Key Confirmation
|
||||
U->>C: Paste private key for confirmation
|
||||
C->>C: Verify pasted key matches generated key
|
||||
U->>C: Confirm registration
|
||||
C->>S: POST /api/register {email, name, public_key}
|
||||
S->>S: Verify email is confirmed
|
||||
S->>S: Store user record
|
||||
S->>C: Registration success response
|
||||
C->>C: Complete registration flow
|
||||
```
|
||||
|
||||
### Registration Data Flow
|
||||
|
||||
1. **Email Collection**
|
||||
```rust
|
||||
struct EmailVerificationRequest {
|
||||
email: String,
|
||||
}
|
||||
```
|
||||
|
||||
2. **Verification Status**
|
||||
```rust
|
||||
struct VerificationStatus {
|
||||
email: String,
|
||||
verified: bool,
|
||||
verification_token: String,
|
||||
}
|
||||
```
|
||||
|
||||
3. **Key Generation** (Client-side)
|
||||
```rust
|
||||
let keypair = generate_keypair()?;
|
||||
let encrypted_key = encrypt_private_key(&keypair.private_key, &password)?;
|
||||
```
|
||||
|
||||
4. **Registration Completion**
|
||||
```rust
|
||||
struct RegistrationRequest {
|
||||
email: String,
|
||||
name: String,
|
||||
public_key: String,
|
||||
}
|
||||
```
|
||||
|
||||
### Security Measures
|
||||
|
||||
- **Email Verification**: Prevents unauthorized registrations
|
||||
- **Key Backup Confirmation**: Ensures user has saved private key
|
||||
- **Client-side Encryption**: Private key never transmitted unencrypted
|
||||
- **Secure Random Generation**: Cryptographically secure key generation
|
||||
- **Password Validation**: Minimum 8 character password requirement
|
||||
|
||||
## Login Flow
|
||||
|
||||
### Step-by-Step Process
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as User
|
||||
participant C as Client (Browser)
|
||||
participant S as Server
|
||||
participant V as Vault System
|
||||
|
||||
Note over U,V: Phase 1: Identity Input
|
||||
U->>C: Enter public key or select identity
|
||||
C->>C: Validate public key format
|
||||
|
||||
Note over U,V: Phase 2: Challenge Generation
|
||||
C->>S: Request authentication challenge
|
||||
S->>S: Generate random challenge
|
||||
S->>C: Return challenge + session info
|
||||
|
||||
Note over U,V: Phase 3: Key Decryption
|
||||
U->>C: Enter password
|
||||
C->>V: Retrieve encrypted private key
|
||||
V->>C: Return encrypted key data
|
||||
C->>C: Decrypt private key with password
|
||||
|
||||
Note over U,V: Phase 4: Challenge Response
|
||||
C->>C: Sign challenge with private key
|
||||
C->>S: POST /oauth/token {signature, public_key, challenge}
|
||||
S->>S: Verify signature against public key
|
||||
S->>S: Generate JWT token
|
||||
S->>C: Return access token
|
||||
|
||||
Note over U,V: Phase 5: Session Establishment
|
||||
C->>C: Store JWT token
|
||||
C->>S: GET /oauth/userinfo (with Bearer token)
|
||||
S->>C: Return user profile
|
||||
C->>C: Complete login flow
|
||||
```
|
||||
|
||||
### OAuth 2.0 Token Request
|
||||
|
||||
The login process follows OAuth 2.0 client credentials flow with cryptographic assertions:
|
||||
|
||||
```rust
|
||||
struct LoginRequest {
|
||||
grant_type: String, // "client_credentials"
|
||||
client_assertion_type: String, // "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
|
||||
client_assertion: String, // Signed JWT containing challenge response
|
||||
public_key: String, // User's public key (client identifier)
|
||||
challenge: String, // Server-provided challenge
|
||||
scope: String, // Requested permissions
|
||||
}
|
||||
```
|
||||
|
||||
### JWT Token Structure
|
||||
|
||||
```rust
|
||||
struct Claims {
|
||||
sub: String, // Subject (public key)
|
||||
iss: String, // Issuer ("self-sovereign-identity")
|
||||
aud: String, // Audience ("identity-server")
|
||||
exp: usize, // Expiration time (1 hour)
|
||||
iat: usize, // Issued at time
|
||||
scope: String, // Granted scopes
|
||||
}
|
||||
```
|
||||
|
||||
### Challenge-Response Mechanism
|
||||
|
||||
1. **Challenge Generation**
|
||||
```rust
|
||||
let challenge = Uuid::new_v4().to_string();
|
||||
```
|
||||
|
||||
2. **Signature Creation** (Client-side)
|
||||
```rust
|
||||
let signature = keypair.sign(&challenge)?;
|
||||
```
|
||||
|
||||
3. **Signature Verification** (Server-side)
|
||||
```rust
|
||||
fn verify_signature(public_key: &str, challenge: &str, signature: &str) -> bool {
|
||||
// Verify signature matches challenge using public key
|
||||
}
|
||||
```
|
||||
|
||||
## Vault-Based Authentication
|
||||
|
||||
### Multi-Key Management
|
||||
|
||||
The vault system allows users to store multiple encrypted keys and authenticate with any of them:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as User
|
||||
participant C as Client
|
||||
participant V as Vault Manager
|
||||
participant S as Server
|
||||
|
||||
U->>C: Select identity from vault
|
||||
C->>V: List available identities
|
||||
V->>C: Return identity list
|
||||
U->>C: Choose identity and enter password
|
||||
C->>V: Decrypt selected identity key
|
||||
V->>C: Return decrypted private key
|
||||
C->>S: Authenticate with selected identity
|
||||
S->>C: Return session for selected identity
|
||||
```
|
||||
|
||||
### Vault Data Structure
|
||||
|
||||
```rust
|
||||
struct VaultEntry {
|
||||
id: String,
|
||||
name: String,
|
||||
email: String,
|
||||
public_key: String,
|
||||
encrypted_private_key: EncryptedPrivateKey,
|
||||
created_at: String,
|
||||
}
|
||||
|
||||
struct EncryptedPrivateKey {
|
||||
encrypted_data: String, // Base64 encoded ciphertext
|
||||
nonce: String, // Base64 encoded nonce
|
||||
salt: String, // Base64 encoded salt
|
||||
}
|
||||
```
|
||||
|
||||
## Session Management
|
||||
|
||||
### JWT Token Lifecycle
|
||||
|
||||
1. **Token Issuance**
|
||||
- Generated after successful authentication
|
||||
- Contains user's public key as subject
|
||||
- 1-hour expiration time
|
||||
- Signed with server secret
|
||||
|
||||
2. **Token Usage**
|
||||
- Included in Authorization header as Bearer token
|
||||
- Required for accessing protected endpoints
|
||||
- Validated on each request
|
||||
|
||||
3. **Token Refresh**
|
||||
- Currently requires re-authentication
|
||||
- Future: Refresh token mechanism
|
||||
|
||||
### Session Storage
|
||||
|
||||
```javascript
|
||||
// Client-side session storage
|
||||
localStorage.setItem('jwt_token', access_token);
|
||||
localStorage.setItem('current_identity', public_key);
|
||||
localStorage.setItem('session_expires', expiration_time);
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Registration Errors
|
||||
|
||||
- **Email Not Verified**: User must complete email verification
|
||||
- **Invalid Email Format**: Client-side validation prevents submission
|
||||
- **Key Generation Failed**: Retry with new random seed
|
||||
- **Encryption Failed**: Check password strength and retry
|
||||
- **Server Unavailable**: Retry with exponential backoff
|
||||
|
||||
### Authentication Errors
|
||||
|
||||
- **Invalid Public Key**: Key format validation and user feedback
|
||||
- **Wrong Password**: Decryption failure, prompt for correct password
|
||||
- **Signature Verification Failed**: Invalid key or challenge tampering
|
||||
- **Token Expired**: Automatic re-authentication flow
|
||||
- **User Not Found**: Public key not registered, redirect to registration
|
||||
|
||||
### Error Response Format
|
||||
|
||||
```rust
|
||||
struct ErrorResponse {
|
||||
error: String, // OAuth 2.0 error code
|
||||
error_description: String, // Human-readable description
|
||||
error_uri: Option<String>, // Optional documentation link
|
||||
}
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Attack Mitigation
|
||||
|
||||
1. **Replay Attacks**: Challenges are single-use and time-limited
|
||||
2. **Man-in-the-Middle**: HTTPS encryption for all communications
|
||||
3. **Key Theft**: Private keys encrypted with user passwords
|
||||
4. **Brute Force**: Rate limiting on authentication attempts
|
||||
5. **Session Hijacking**: JWT tokens with short expiration times
|
||||
|
||||
### Privacy Protection
|
||||
|
||||
- **No Password Storage**: Server never sees user passwords
|
||||
- **Minimal Data Collection**: Only email and public key stored
|
||||
- **Local Key Storage**: Private keys never leave user's device
|
||||
- **Anonymous Usage**: Public keys don't reveal personal information
|
||||
|
||||
### Compliance Considerations
|
||||
|
||||
- **GDPR**: Users control their own data, right to deletion
|
||||
- **OAuth 2.0**: Standard token-based authentication
|
||||
- **OpenID Connect**: Compatible user info endpoint
|
||||
- **WebAuthn**: Future integration for hardware token support
|
||||
Reference in New Issue
Block a user