Skip to content

JWT Authentication Quick Reference

JWT Authentication Quick Reference

Quick guide for using JWT authentication in HeliosDB Nano sync protocol

Quick Start

Server Setup (5 lines)

use heliosdb_nano::sync::SyncServer;
// Create server with JWT authentication
let mut server = SyncServer::with_jwt_secret(b"your-secret-key");
// Add allowed tenants
server.add_tenant("tenant-1".to_string());
// Generate tokens for client
let token_pair = server.generate_token_pair(
"user@example.com".to_string(),
"tenant-1".to_string(),
client_id,
)?;
// Handle authenticated request
let response = server.handle_sync_request(request, &token_pair.access_token).await?;

Client Setup (4 lines)

use heliosdb_nano::sync::{SyncClient, SyncConfig};
// Create client
let mut client = SyncClient::new(SyncConfig::default())?;
// Set tokens from server
client.set_tokens(token_pair);
// Sync (authentication automatic)
let result = client.sync_once().await?;

Common Operations

Generate Token Pair

let token_pair = server.generate_token_pair(
user_id.to_string(),
tenant_id.to_string(),
client_id,
)?;
// token_pair.access_token - For sync operations
// token_pair.refresh_token - For refreshing access token

Validate Token

let claims = jwt_manager.validate_token(&access_token)?;
// Check claims
assert_eq!(claims.sub, "user123");
assert_eq!(claims.tenant_id, "tenant456");
assert!(!claims.is_expired());

Refresh Access Token

// Server side
let new_access = server.refresh_token(&refresh_token)?;
// Client side (automatic)
let token = client.get_valid_token().await?; // Auto-refreshes if expired

Check Authentication

// Client side
if !client.is_authenticated() {
// Need to authenticate
client.set_tokens(token_pair);
}
// Server side
let claims = server.authenticate(&jwt_token).await?;

Token Claims

pub struct Claims {
pub sub: String, // User ID
pub tenant_id: String, // Tenant ID
pub client_id: Uuid, // Client ID
pub exp: u64, // Expiration (Unix timestamp)
pub iat: u64, // Issued at (Unix timestamp)
pub nbf: u64, // Not before (Unix timestamp)
pub jti: String, // JWT ID (unique)
pub iss: String, // Issuer ("heliosdb-sync")
pub aud: String, // Audience ("heliosdb-client")
pub scopes: Vec<String>, // Permissions
}

Error Handling

match client.sync_once().await {
Ok(result) => println!("Synced {} rows", result.synced_rows),
Err(SyncError::Authentication) => {
// Token invalid or expired
// Re-authenticate with server
},
Err(e) => eprintln!("Sync error: {}", e),
}

Configuration

Environment Variable

Terminal window
export HELIOSDB_JWT_SECRET="your-production-secret-key"

Custom Expiry

let jwt_manager = JwtManager::new(b"secret")
.with_expiry(
Duration::hours(2), // Access: 2 hours
Duration::days(30), // Refresh: 30 days
);

Custom Authorization

// Create authorizer with specific tenants
let mut authorizer = Authorizer::with_tenants(vec![
"tenant-a".to_string(),
"tenant-b".to_string(),
]);
// Create server with custom auth
let server = SyncServer::with_auth(jwt_manager, authorizer);

Testing

Terminal window
# Run JWT auth tests
cargo test jwt_auth
# Run specific test
cargo test test_full_authentication_flow
# With debug output
RUST_LOG=debug cargo test jwt_auth -- --nocapture

Common Patterns

Client Registration Flow

// 1. Server generates tokens
let token_pair = server.generate_token_pair(user_id, tenant_id, client_id)?;
// 2. Send to client (secure channel)
// ... transmit token_pair ...
// 3. Client stores tokens
client.set_tokens(token_pair);
// 4. Client syncs
client.sync_once().await?;

Token Refresh Flow

// Client automatically refreshes on sync
let result = client.sync_once().await?; // Auto-refresh if needed
// Manual refresh
let new_token = jwt_manager.refresh_access_token(&refresh_token)?;

Multi-Tenant Setup

// Server setup
let mut server = SyncServer::new();
server.add_tenant("customer-1".to_string());
server.add_tenant("customer-2".to_string());
// Generate tokens for each tenant
let tokens_1 = server.generate_token_pair("user1", "customer-1", client1)?;
let tokens_2 = server.generate_token_pair("user2", "customer-2", client2)?;
// Each client can only access their tenant's data

Security Checklist

  • Use strong random secret (>32 bytes)
  • Store secret in environment variable
  • Use HTTPS/TLS for all communication
  • Set appropriate token expiry (1 hour recommended)
  • Implement token refresh flow
  • Validate tenant authorization
  • Never log tokens
  • Clear tokens on logout
  • Monitor authentication failures

Troubleshooting

ErrorCauseSolution
JWT validation failedWrong secretCheck secret matches
Token expiredPast expirationUse refresh token
Unauthorized tenantNot in allowed listAdd tenant with server.add_tenant()
Client ID mismatchWrong clientGenerate new token for client
Authentication errorNo token setCall client.set_tokens()

Performance Tips

  1. Cache validated tokens (server-side) for repeated requests
  2. Use short expiry (1 hour) for access tokens
  3. Implement refresh tokens to minimize re-authentication
  4. Enable compression for token transmission
  5. Monitor token generation rate limits

API Reference

Server Methods

server.with_jwt_secret(secret: &[u8]) -> Self
server.generate_token(user_id, tenant_id, client_id) -> Result<String>
server.generate_token_pair(user_id, tenant_id, client_id) -> Result<TokenPair>
server.refresh_token(refresh_token: &str) -> Result<String>
server.add_tenant(tenant_id: String)
server.remove_tenant(tenant_id: &str) -> bool
server.handle_sync_request(request, jwt_token: &str) -> Result<SyncResponse>

Client Methods

client.set_tokens(token_pair: TokenPair)
client.set_auth_tokens(access: String, refresh: String)
client.is_authenticated() -> bool
client.access_token() -> Option<&str>
client.refresh_token() -> Option<&str>
client.sync_once() -> Result<SyncResult>

JWT Manager Methods

jwt_manager.new(secret: &[u8]) -> Self
jwt_manager.generate_token(user_id, tenant_id, client_id) -> Result<String>
jwt_manager.generate_refresh_token(user_id, tenant_id, client_id) -> Result<String>
jwt_manager.validate_token(token: &str) -> Result<Claims>
jwt_manager.validate_with_scope(token: &str, scope: &str) -> Result<Claims>
jwt_manager.refresh_access_token(refresh_token: &str) -> Result<String>

Authorizer Methods

authorizer.new() -> Self
authorizer.with_tenants(tenants: Vec<String>) -> Self
authorizer.is_authorized(tenant_id: &str) -> bool
authorizer.add_tenant(tenant_id: String)
authorizer.remove_tenant(tenant_id: &str) -> bool
authorizer.validate_claims(claims: &Claims) -> Result<()>

File Locations

  • Auth Module: /home/claude/HeliosDB Nano/src/sync/auth.rs
  • Server: /home/claude/HeliosDB Nano/src/sync/server.rs
  • Client: /home/claude/HeliosDB Nano/src/sync/client.rs
  • Tests: /home/claude/HeliosDB Nano/tests/jwt_auth_integration_tests.rs
  • Docs: /home/claude/HeliosDB Nano/docs/implementation/JWT_AUTHENTICATION_IMPLEMENTATION.md

Next Steps

  1. Set up JWT secret in production
  2. Configure tenant authorization
  3. Implement client registration endpoint
  4. Add token revocation (optional)
  5. Enable audit logging (optional)

For detailed documentation, see: docs/implementation/JWT_AUTHENTICATION_IMPLEMENTATION.md