CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-ktor--ktor-client-auth

Ktor client authentication and authorization plugin that handles various authentication schemes including Basic, Bearer, and Digest authentication.

Pending
Overview
Eval results
Files

digest-auth.mddocs/

Digest Authentication

Challenge-response authentication using HTTP Digest authentication scheme. Provides improved security over Basic auth by using cryptographic hashes instead of plain text credentials.

Capabilities

Digest Provider Installation

Install Digest authentication with credential and algorithm configuration.

/**
 * Install Digest authentication provider
 * @param block Configuration block for DigestAuthConfig
 */
fun AuthConfig.digest(block: DigestAuthConfig.() -> Unit)

Usage Example:

install(Auth) {
    digest {
        credentials {
            // Load from secure storage
            val creds = credentialStorage.getDigestCredentials()
            DigestAuthCredentials(creds.username, creds.password)
        }
        
        algorithmName = "MD5" // Default hash algorithm
        realm = "Protected Area" // Optional realm restriction
    }
}

DigestAuthCredentials Class

Container for Digest authentication credentials.

/**
 * Container for digest authentication credentials
 * @param username The username for authentication
 * @param password The password for authentication (used for hash computation)
 */
class DigestAuthCredentials(
    val username: String,
    val password: String
)

DigestAuthConfig Class

Configuration for Digest authentication provider.

/**
 * Configuration for Digest authentication
 */
class DigestAuthConfig {
    /**
     * Hash algorithm for digest computation (default: "MD5")
     */
    var algorithmName: String
    
    /**
     * Optional realm restriction for this provider
     */
    var realm: String?
    
    /**
     * Configure callback to load authentication credentials
     * @param block Function that returns credentials or null
     */
    fun credentials(block: suspend () -> DigestAuthCredentials?)
}

DigestAuthProvider Class

Implementation of Digest authentication provider with challenge-response handling.

/**
 * Digest authentication provider implementation
 */
class DigestAuthProvider(
    private val credentials: suspend () -> DigestAuthCredentials?,
    val realm: String? = null,
    val algorithmName: String = "MD5"
) : AuthProvider {
    /**
     * Clear cached credentials from memory
     * Call when credentials are updated or during logout
     * Note: This is an internal API and may change in future versions
     */
    @InternalAPI
    fun clearToken()
}

Authentication Flow

Challenge-Response Process

  1. Initial Request: Client makes request without authentication
  2. 401 Challenge: Server responds with WWW-Authenticate header containing nonce and other parameters
  3. Response Calculation: Client computes digest using credentials and challenge parameters
  4. Authenticated Request: Client retries with Authorization header containing computed digest

Digest Computation

The digest is calculated using this process:

HA1 = MD5(username:realm:password)
HA2 = MD5(method:uri)
response = MD5(HA1:nonce:nc:cnonce:qop:HA2)

Where:

  • nonce: Random value from server challenge
  • nc: Request counter (hexadecimal, zero-padded to 8 digits)
  • cnonce: Client-generated random value
  • qop: Quality of protection (from server challenge)

Challenge Parameters

Digest authentication handles these WWW-Authenticate parameters:

  • realm: Authentication realm (required)
  • nonce: Server-generated random value (required)
  • qop: Quality of protection (optional)
  • opaque: Server-specific data (optional)
  • algorithm: Hash algorithm, defaults to MD5

Example Challenge:

WWW-Authenticate: Digest realm="Protected Area", 
                  nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
                  qop="auth",
                  opaque="5ccc069c403ebaf9f0171e9517f40e41"

Usage Examples

Simple Digest Authentication

install(Auth) {
    digest {
        credentials {
            DigestAuthCredentials("user", "password")
        }
    }
}

Advanced Configuration

install(Auth) {
    digest {
        credentials {
            // Load from secure configuration
            val config = loadSecureConfig()
            DigestAuthCredentials(
                username = config.digestUsername,
                password = config.digestPassword
            )
        }
        
        algorithmName = "SHA-256" // Use stronger algorithm if supported
        realm = "API Access" // Restrict to specific realm
    }
}

Multiple Digest Providers

install(Auth) {
    // Admin realm
    digest {
        credentials { getAdminDigestCredentials() }
        realm = "Admin"
    }
    
    // User realm
    digest {
        credentials { getUserDigestCredentials() }
        realm = "User"
        algorithmName = "SHA-256"
    }
}

Security Features

Improved Security over Basic Auth

  • No Plain Text: Password is never sent over network
  • Nonce Protection: Server nonce prevents replay attacks
  • Request Counting: nc parameter prevents replay attacks
  • Client Nonce: cnonce adds additional randomness

Hash Algorithms

Supported algorithms (server dependent):

  • MD5: Default, widely supported but cryptographically weak
  • SHA-256: Stronger hash function, better security
  • SHA-512: Even stronger, limited server support

Quality of Protection (QOP)

  • auth: Authentication only (default)
  • auth-int: Authentication with integrity protection (includes request body hash)

Request Counter Management

The provider automatically manages request counters:

  • Each provider maintains an atomic counter
  • Counter increments with each authenticated request
  • Counter value is formatted as 8-digit hexadecimal
  • Prevents replay attacks when used with nonces

Error Scenarios

  • Missing Nonce: Provider rejects challenges without nonce parameter
  • Missing Realm: Provider rejects challenges without realm parameter
  • Realm Mismatch: Provider ignores challenges for different realms
  • Invalid Credentials: Server returns 401/403 for incorrect digest
  • Unsupported Algorithm: Provider defaults to MD5 if algorithm unsupported

Limitations

  • Server Support: Not all servers support Digest authentication
  • Algorithm Negotiation: Limited algorithm support across servers
  • Performance: Hash computation adds processing overhead
  • No Token Refresh: No automatic credential refresh mechanism
  • MD5 Weakness: Default MD5 algorithm has known cryptographic weaknesses

Security Considerations

  • Use HTTPS: While more secure than Basic auth, HTTPS is still recommended
  • Strong Passwords: Password strength is critical since it's used in hash computation
  • Algorithm Choice: Use SHA-256 or stronger when server supports it
  • Credential Storage: Store credentials securely using platform-specific secure storage
  • Session Management: Clear credentials on logout or session expiration

Migration from Basic Auth

To migrate from Basic to Digest authentication:

// Before: Basic Auth
install(Auth) {
    basic {
        credentials { BasicAuthCredentials("user", "pass") }
    }
}

// After: Digest Auth
install(Auth) {
    digest {
        credentials { DigestAuthCredentials("user", "pass") }
        algorithmName = "SHA-256" // Upgrade algorithm if possible
    }
}

No code changes needed in request handling - the provider handles all digest computation automatically.

Install with Tessl CLI

npx tessl i tessl/maven-io-ktor--ktor-client-auth

docs

auth-plugin.md

basic-auth.md

bearer-auth.md

digest-auth.md

index.md

tile.json