server_verify/
server_verify.rs1use broadcast_auth::{AuthResult, Credentials, RequestContext, Verifier, respond};
18
19const REALM: &str = "cameras";
20
21fn main() {
22 digest();
23 basic();
24 bearer();
25 forwarded();
26}
27
28fn digest() {
31 let verifier = Verifier::new(
32 Credentials::Digest {
33 username: "admin".into(),
34 password: "hunter2".into(),
35 },
36 REALM,
37 );
38 let challenge = verifier.challenge();
39 println!("[digest] challenge: {challenge}");
40
41 let ctx = RequestContext::new("DESCRIBE", "rtsp://cam/live");
42
43 let correct = respond(&challenge, &ctx, Credentials::new("admin", "hunter2"))
45 .expect("respond computes an Authorization value");
46 let outcome = verify(&verifier, &correct, &ctx);
47 println!("[digest] correct password -> {outcome:?}");
48 assert_eq!(outcome, AuthResult::Ok);
49
50 let wrong = respond(&challenge, &ctx, Credentials::new("admin", "WRONG"))
52 .expect("respond computes an Authorization value even for a wrong password");
53 let outcome = verify(&verifier, &wrong, &ctx);
54 println!("[digest] wrong password -> {outcome:?}");
55 assert_eq!(outcome, AuthResult::Unauthorized);
56}
57
58fn basic() {
60 let verifier = Verifier::new(
61 Credentials::Basic {
62 username: "admin".into(),
63 password: "hunter2".into(),
64 },
65 REALM,
66 );
67 let challenge = verifier.challenge();
68 println!("[basic] challenge: {challenge}");
69
70 let ctx = RequestContext::new("GET", "/stream/media.m3u8");
71 let correct =
72 respond(&challenge, &ctx, Credentials::new("admin", "hunter2")).expect("responds");
73 assert_eq!(verify(&verifier, &correct, &ctx), AuthResult::Ok);
74 println!("[basic] correct password -> Ok");
75
76 let wrong = respond(&challenge, &ctx, Credentials::new("admin", "WRONG")).expect("responds");
77 assert_eq!(verify(&verifier, &wrong, &ctx), AuthResult::Unauthorized);
78 println!("[basic] wrong password -> Unauthorized");
79}
80
81fn bearer() {
84 let verifier = Verifier::new(Credentials::bearer("right-token"), REALM);
85 let challenge = verifier.challenge();
86 println!("[bearer] challenge: {challenge}");
87
88 let ctx = RequestContext::new("GET", "/stream/media.m3u8");
89 let correct = respond(&challenge, &ctx, Credentials::bearer("right-token")).expect("responds");
90 assert_eq!(verify(&verifier, &correct, &ctx), AuthResult::Ok);
91 println!("[bearer] correct token -> Ok");
92
93 let wrong = respond(&challenge, &ctx, Credentials::bearer("wrong-token")).expect("responds");
94 assert_eq!(verify(&verifier, &wrong, &ctx), AuthResult::Unauthorized);
95 println!("[bearer] wrong token -> Unauthorized");
96}
97
98fn forwarded() {
104 let verifier = Verifier::forwarded("X-Forwarded-User", Some("X-Forwarded-For".to_string()));
105 println!("[forwarded] challenge: {}", verifier.challenge());
106
107 let headers: &[(&str, &str)] = &[("X-Forwarded-User", "alice")];
108 let ctx = RequestContext::new("GET", "/stream/media.m3u8").with_headers(headers);
109 assert_eq!(verifier.verify(&ctx), AuthResult::Ok);
110 println!("[forwarded] header present -> Ok");
111
112 let ctx_no_header = RequestContext::new("GET", "/stream/media.m3u8");
113 assert_eq!(verifier.verify(&ctx_no_header), AuthResult::Unauthorized);
114 println!("[forwarded] header absent -> Unauthorized");
115}
116
117fn verify(verifier: &Verifier, authorization: &str, ctx: &RequestContext<'_>) -> AuthResult {
120 let headers: &[(&str, &str)] = &[("authorization", authorization)];
121 let ctx_with_auth = RequestContext::new(ctx.method, ctx.uri).with_headers(headers);
122 verifier.verify(&ctx_with_auth)
123}