Trait TenantResolver

Source
pub trait TenantResolver: Send + Sync {
    type Error: Error + Send + Sync + 'static;

    // Required methods
    fn resolve_tenant(
        &self,
        credential: &str,
    ) -> impl Future<Output = Result<TenantContext, Self::Error>> + Send;
    fn validate_tenant(
        &self,
        tenant_id: &str,
    ) -> impl Future<Output = Result<bool, Self::Error>> + Send;

    // Provided methods
    fn list_tenants(
        &self,
    ) -> impl Future<Output = Result<Vec<String>, Self::Error>> + Send { ... }
    fn is_valid_credential(
        &self,
        credential: &str,
    ) -> impl Future<Output = Result<bool, Self::Error>> + Send { ... }
}
Expand description

Trait for resolving tenant contexts from authentication credentials.

Implementations of this trait are responsible for mapping authentication information (such as API keys, JWT tokens, or other credentials) to tenant contexts that define the scope and permissions for operations.

§Security Considerations

  • Always validate credentials before returning tenant context
  • Implement rate limiting to prevent brute force attacks
  • Log authentication attempts for audit purposes
  • Use secure credential storage and comparison

§Example Implementation

use scim_server::multi_tenant::TenantResolver;
use scim_server::TenantContext;
use std::collections::HashMap;

struct DatabaseTenantResolver {
    // In a real implementation, this would be a database connection
    credentials: HashMap<String, TenantContext>,
}

#[derive(Debug, thiserror::Error)]
#[error("Database resolver error: {message}")]
struct DatabaseError {
    message: String,
}

impl TenantResolver for DatabaseTenantResolver {
    type Error = DatabaseError;

    async fn resolve_tenant(&self, credential: &str) -> Result<TenantContext, Self::Error> {
        self.credentials
            .get(credential)
            .cloned()
            .ok_or_else(|| DatabaseError { message: "Invalid credentials".to_string() })
    }

    async fn validate_tenant(&self, tenant_id: &str) -> Result<bool, Self::Error> {
        Ok(self.credentials.values().any(|ctx| ctx.tenant_id == tenant_id))
    }
}

Required Associated Types§

Source

type Error: Error + Send + Sync + 'static

Error type for resolver operations

Required Methods§

Source

fn resolve_tenant( &self, credential: &str, ) -> impl Future<Output = Result<TenantContext, Self::Error>> + Send

Resolve a tenant context from authentication credentials.

§Arguments
  • credential - Authentication credential (API key, token, etc.)
§Returns

The tenant context if credentials are valid

§Errors

Returns an error if:

  • Credentials are invalid
  • Tenant is not found
  • Tenant is disabled/suspended
  • Database/storage access fails
Source

fn validate_tenant( &self, tenant_id: &str, ) -> impl Future<Output = Result<bool, Self::Error>> + Send

Validate that a tenant exists and is active.

§Arguments
  • tenant_id - The tenant identifier to validate
§Returns

True if the tenant exists and is active

§Errors

Returns an error if validation fails due to system issues

Provided Methods§

Source

fn list_tenants( &self, ) -> impl Future<Output = Result<Vec<String>, Self::Error>> + Send

Get all active tenant IDs (useful for admin operations).

§Returns

A vector of all active tenant identifiers

§Errors

Returns an error if tenant enumeration fails

Source

fn is_valid_credential( &self, credential: &str, ) -> impl Future<Output = Result<bool, Self::Error>> + Send

Check if a credential is valid without returning the full context.

This is useful for lightweight authentication checks.

§Arguments
  • credential - Authentication credential to validate
§Returns

True if the credential is valid

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§