#http #auth #digest

digest_auth

Implementation of the Digest Auth algorithm as defined in IETF RFC 2069, 2617, and 7616, intended for HTTP clients

6 releases

✓ Uses Rust 2018 edition

new 0.2.1 Oct 9, 2019
0.2.0 Oct 6, 2019
0.1.3 Oct 5, 2019
0.1.2 Feb 27, 2019

#55 in Authentication

Download history 17/week @ 2019-06-26 24/week @ 2019-07-03 12/week @ 2019-07-10 4/week @ 2019-07-17 1/week @ 2019-07-24 6/week @ 2019-07-31 10/week @ 2019-08-07 3/week @ 2019-08-14 13/week @ 2019-08-21 18/week @ 2019-08-28 16/week @ 2019-09-04 8/week @ 2019-09-11 25/week @ 2019-09-18 10/week @ 2019-09-25 39/week @ 2019-10-02

56 downloads per month

MIT license

48KB
1K SLoC

Rust implementation of Digest Auth hashing algorithms, as defined in IETF RFC 2069, 2617, and 7616.

This crate provides the authentication header parsing and generation code.


lib.rs:

This crate implements Digest Auth headers as specified by IETF RFCs 2069, 2617, and 7616. It can be used in conjunction with libraries like reqwest to access e.g. IP cameras that use this authentication scheme.

This library was written for the http client, but since the algorithm is symmetrical, it can be used by the server side as well. Server-side nonce management (generation, timed expiry) and authorization checking is left to user's implementation.

The AuthorizationHeader::digest() method can be used server-side to replicate the password/body hash; then just check if the computed digest matches what the user sent.

Examples

Basic usage:

use digest_auth::AuthContext;

// Value from the WWW-Authenticate HTTP header (usually in a HTTP 401 response)
let www_authenticate = r#"Digest realm="http-auth@example.org", qop="auth, auth-int", algorithm=MD5, nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v", opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS""#;

// Prepare an authorization context. Note that this is a GET request. There are different
// constructors available for POST or other request types. You can re-use it, but
// it's cheap to create a fresh one each time, as the struct uses references only.
let mut context = AuthContext::new("Mufasa", "Circle of Life", "/dir/index.html");
// For this test, we inject a custom cnonce. It's generated for you otherwise
// - you don't need `mut` in that case and needn't worry about this at all.
context.set_custom_cnonce("f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ");

// Parse the prompt header. You can inspect the parsed object, its fields are public.
let mut prompt = digest_auth::parse(www_authenticate).unwrap();

// Compute a value for the Authorization header that we'll send back to the server
let answer = prompt.respond(&context).unwrap().to_string();
assert_eq!(answer, r#"Digest username="Mufasa", realm="http-auth@example.org", nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v", uri="/dir/index.html", qop=auth, nc=00000001, cnonce="f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ", response="8ca523f5e9506fed4657c9700eebdbec", opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS", algorithm=MD5"#);

// The `prompt` variable is mutable, because the 'nc' counter (nonce reuse count)
// is inside the struct and updated automatically.

// You can re-use it for subsequent requests, assuming the server allows nonce re-use.
// Some poorly implemented servers will reject it and give you 401 again, in which case
// you should parse the new "WWW-Authenticate" header and use that instead.

let answer2 = prompt.respond(&context).unwrap().to_string();
// notice how the 'response' field changed - the 'nc' counter is included in the hash
assert_eq!(answer2, r#"Digest username="Mufasa", realm="http-auth@example.org", nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v", uri="/dir/index.html", qop=auth, nc=00000002, cnonce="f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ", response="4b5d595ecf2db9df612ea5b45cd97101", opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS", algorithm=MD5"#);

Dependencies

~3MB
~40K SLoC