Digest authentication in Ktor Server
The Digest authentication scheme is a part of the HTTP framework used for access control and authentication. In this scheme, a hash function is applied to a username and password before sending them over the network.
Ktor supports RFC 7616 (HTTP Digest Access Authentication), which enhances the older RFC 2617 with modern security features including stronger hash algorithms, quality of protection options, and username hashing for privacy.
Ktor allows you to use digest authentication for logging in users and protecting specific routes. You can get general information about authentication in Ktor in the Authentication and authorization in Ktor Server section.
Add dependencies
To enable digest authentication, you need to include the ktor-server-auth artifact in the build script:
Digest authentication flow
The digest authentication flow looks as follows:
A client makes a request without the
Authorizationheader to a specific route in a server application.A server responds to a client with a
401(Unauthorized) response status and uses aWWW-Authenticateresponse header to provide information that the digest authentication scheme is used to protect a route. A typicalWWW-Authenticateheader looks like this:WWW-Authenticate: Digest realm="Access to the '/' path", nonce="e4549c0548886bc2", algorithm=SHA-512-256, qop="auth"In Ktor, you can specify the realm, supported algorithms, quality of protection, and the way of generating a nonce value when configuring the
digestauthentication provider.Usually a client displays a login dialog where a user can enter credentials. Then, a client makes a request with the following
Authorizationheader:Authorization: Digest username="jetbrains", realm="Access to the '/' path", nonce="e4549c0548886bc2", uri="/", algorithm=SHA-512-256, qop=auth, nc=00000001, cnonce="0a4f113b", response="6629fae49393a05397450978507c4ef1"The
responsevalue is generated in the following way:HA1 = H(username:realm:password)whereHis the configured hash algorithm (e.g., SHA-512-256)
HA2 = H(method:digestURI)(forqop=auth) orHA2 = H(method:digestURI:H(entityBody))(forqop=auth-int)response = H(HA1:nonce:nc:cnonce:qop:HA2)
A server validates the credentials sent by a client and responds with the requested content. On successful authentication with QoP, the server also returns an
Authentication-Infoheader for mutual authentication.
Install digest authentication
To install the digest authentication provider, call the digest function inside the install block:
You can optionally specify a provider name that can be used to authenticate a specified route.
Configure digest authentication
To get a general idea of how to configure different authentication providers in Ktor, see Configure Authentication. In this section, we'll see on configuration specifics of the digest authentication provider.
Step 1: Choose hash algorithms
Ktor supports multiple hash algorithms for digest authentication. You can configure which algorithms your server accepts using the algorithms property:
Algorithm | Constant | Security Level | Notes |
|---|---|---|---|
SHA-512-256 |
| Recommended | Strongest security, use for new implementations |
SHA-512-256-sess |
| Recommended | Session variant - includes client nonce in HA1 |
SHA-256 |
| Good | Minimum recommended for production |
SHA-256-sess |
| Good | Session variant - includes client nonce in HA1 |
MD5 |
| Deprecated | Only for backward compatibility |
MD5-sess |
| Deprecated | Session variant - only for legacy compatibility |
When multiple algorithms are configured, the server sends multiple WWW-Authenticate headers, allowing clients to choose the strongest algorithm they support.
Session algorithms (-sess variants)
The -sess algorithm variants (e.g., SHA-512-256-sess, SHA-256-sess, MD5-sess) modify how the HA1 hash is computed. Instead of storing H(username:realm:password), session algorithms compute H(H(username:realm:password):nonce:cnonce), where cnonce is client-provided nonce.
Benefits:
The session-specific hash prevents pre-computed dictionary attacks
Compromising one session's hash doesn't reveal the password or help with other sessions
Drawback:
The server must compute the hash for each authentication request (cannot use pre-computed values)
For most applications, the standard (non-session) algorithms are sufficient, especially when used with strong hash functions like SHA-512-256.
Step 2: Provide a user table with digests
The digest authentication provider validates user credentials using the HA1 part of a digest message, so you can provide a user table that contains usernames and their corresponding HA1 hashes.
Since different algorithms produce different hash values, you need to store the appropriate hash for each algorithm you support or compute the hash dynamically based on the algorithm requested by the client:
Step 3: Configure a digest provider
The digest authentication provider exposes its settings via the DigestAuthenticationProvider.Config class. In the example below, the following settings are specified:
The
realmproperty sets the realm to be passed in theWWW-Authenticateheader.The
algorithmsproperty specifies which hash algorithms to accept.The
digestProviderfunction fetches theHA1part of digest for a specified username and algorithm.(Optional) The
validatefunction allows you to map the credentials to a custom principal.
The digestProvider function receives three parameters:
userName- the username from the client's requestrealm- the configured realmalgorithm- the hash algorithm the client is using
You should return the HA1 hash computed with the specified algorithm, or null if the user is not found.
You can also use the nonceManager property to specify how to generate nonce values.
Step 4: Configure Quality of Protection
Quality of Protection (QoP) determines what is included in the digest calculation:
DigestQop.AUTH- Authentication only (default). The digest includes the request method and URI.DigestQop.AUTH_INT- Authentication with integrity protection. The digest also includes the request body, providing protection against tampering.
Step 5: Protect specific resources
After configuring the digest provider, you can protect specific resources in our application using the authenticate function. In the case of successful authentication, you can retrieve an authenticated Principal inside a route handler using the call.principal function and get a name of an authenticated user.
Advanced configuration
User hash support
RFC 7616 introduces username hashing (userhash) for privacy protection. When enabled, clients can send a hashed version of the username instead of the plaintext username.
To support username hashing, configure a userHashResolver:
When userHashResolver is configured, the server advertises userhash=true in the WWW-Authenticate challenge header.
Strict RFC 7616 mode
For maximum security in new applications without legacy client requirements, use strictRfc7616Mode():
Strict mode:
Removes MD5 algorithms (only allows SHA-256, SHA-512-256, and their session variants)
Enforces UTF-8 charset
UTF-8 charset support
The digest authentication provider supports UTF-8 charset for usernames and passwords containing non-ASCII characters:
Authentication-Info header
On successful authentication with QoP, the server automatically returns an Authentication-Info header containing:
rspauth- Response authentication value for mutual authenticationnextnonce- Next nonce for the client to useqop,nc,cnonce- Echo of authentication parameters
This allows clients to verify the server's identity (mutual authentication).
Security recommendations
Use SHA-512-256 or SHA-256 - Avoid MD5 in production; it's only included for legacy compatibility.
Use
strictRfc7616Mode()- For new applications without legacy client requirements.Implement proper nonce management – Use a custom
NonceManagerto prevent replay attacks in distributed environments.Consider
auth-int- When request body integrity is important for your application.Enable
userhash- For privacy protection of usernames.Always use HTTPS – Digest authentication alone doesn't encrypt traffic; always use TLS in production.