~whynothugo/pimsync#31: 
Support digest Auth

The main steps involved in Digest authentication are as follows:

  • Client sends a request to the server that requires authentication.
  • Server responds with a 401 Unauthorized status code and provides a "WWW-Authenticate" header that includes the authentication realm and other required information.
  • The client resends the request with the "Authorization" header, which includes a hashed value of the user's credentials.
Status
REPORTED
Submitter
~whynothugo
Assigned to
No-one
Submitted
1 year, 11 months ago
Updated
a month ago
Labels
0:missing-feature 3:libdav 4:patches-welcome

~whynothugo 1 year, 11 months ago*

Quite untested:

use ring::digest;

fn calculate_digest(username: &str, realm: &str, password: &str, method: &str, uri: &str, nonce: &str, cnonce: &str) -> String {
    let ha1 = format!("{}:{}:{}", username, realm, password);
    let ha1_digest = digest::digest(&digest::MD5, ha1.as_bytes());

    let ha2 = format!("{}:{}", method, uri);
    let ha2_digest = digest::digest(&digest::MD5, ha2.as_bytes());

    let response = format!("{:x}:{nonce}:{nc}:{cnonce}:{qop}:{ha2}", ha1_digest, nonce, "00000001", cnonce, "auth", ha2_digest);
    let response_digest = digest::digest(&digest::MD5, response.as_bytes());

    format!("{:x}", response_digest)
}

fn main() {
    let username = "alice";
    let realm = "realm";
    let password = "password";
    let method = "GET";
    let uri = "/path";
    let nonce = "1234567890";
    let cnonce = "0987654321";

    let digest = calculate_digest(username, realm, password, method, uri, nonce, cnonce);
    println!("Digest: {}", digest);
}

The main pain point is the extra request to get the WWW-Authenticate header with the realm and stuff. I wonder if this can be done in a separate step or something (e.g. have the value ready before sync).

~whynothugo 1 year, 2 months ago

Baikal supports digest auth.

~whynothugo 1 year, 5 days ago

Digest auth requires a round trip before the real request, so the auth mechanism needs to provide an async function. This function takes the original request and applies auth to it.

In case of basic auth, the above function merely adds a header.

In case of digest auth, the above function does a separate http request to determine the realm and other data, and the adds the header to the original request.

Register here or Log in to comment, or comment via email.