client_respond/
client_respond.rs1use broadcast_auth::{Authenticator, Credentials, RequestContext, respond};
17
18fn main() {
19 let value = respond(
21 "Basic realm=\"cameras\"",
22 &RequestContext::new("GET", "/stream/media.m3u8"),
23 Credentials::new("admin", "hunter2"),
24 )
25 .expect("Basic responds to any challenge shape");
26 println!("[basic] Authorization: {value}");
27 assert!(value.starts_with("Basic "));
28
29 let digest_challenge = "Digest realm=\"cameras\", \
34 nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", qop=\"auth\", algorithm=MD5";
35 let mut auth =
36 Authenticator::from_challenge(digest_challenge, Credentials::new("admin", "hunter2"))
37 .expect("challenge parses");
38 let value = auth
39 .authorization(&RequestContext::new(
40 "DESCRIBE",
41 "rtsp://camera.example.com/live",
42 ))
43 .expect("computes a Digest Authorization value");
44 println!("[digest] Authorization: {value}");
45 assert!(value.starts_with("Digest "));
46
47 let second = auth
51 .authorization(&RequestContext::new(
52 "DESCRIBE",
53 "rtsp://camera.example.com/live",
54 ))
55 .expect("computes a second Digest Authorization value");
56 assert_ne!(value, second, "nc must advance across requests");
57 println!("[digest] Authorization (2nd request, nc advanced): {second}");
58
59 let value = respond(
62 "ignored — Bearer needs no challenge round-trip",
63 &RequestContext::new("GET", "/stream/media.m3u8"),
64 Credentials::bearer("mytoken123"),
65 )
66 .expect("Bearer always responds");
67 println!("[bearer] Authorization: {value}");
68 assert_eq!(value, "Bearer mytoken123");
69}