Skip to content

Commit ddb2795

Browse files
committed
Use feature for LNURL Auth JWT headers
1 parent ac4bb96 commit ddb2795

File tree

3 files changed

+105
-96
lines changed

3 files changed

+105
-96
lines changed

Cargo.toml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,20 @@ categories = ["web-programming::http-client", "cryptography::cryptocurrencies"]
1111

1212
build = "build.rs"
1313

14+
[features]
15+
lnurl-auth = ["dep:bitcoin", "dep:url", "dep:base64", "dep:serde", "dep:serde_json"]
16+
1417
[dependencies]
1518
prost = "0.11.6"
1619
reqwest = { version = "0.11.13", default-features = false, features = ["rustls-tls", "json"] }
1720
tokio = { version = "1", default-features = false, features = ["time"] }
1821
rand = "0.8.5"
19-
bitcoin = "0.30.2"
22+
bitcoin = { version = "0.30.2", optional = true }
2023
async-trait = "0.1.77"
21-
url = "2.5.0"
22-
base64 = "0.21.7"
23-
serde = { version = "1.0.196", features = ["serde_derive"] }
24-
serde_json = "1.0.113"
24+
url = { version = "2.5.0", optional = true }
25+
base64 = { version = "0.21.7", optional = true }
26+
serde = { version = "1.0.196", features = ["serde_derive"], optional = true }
27+
serde_json = { version = "1.0.113", optional = true }
2528

2629
[target.'cfg(genproto)'.build-dependencies]
2730
prost-build = { version = "0.11.3" }

src/headers/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ use std::fmt::Display;
66
use std::fmt::Formatter;
77
use std::str::FromStr;
88

9+
#[cfg(feature = "lnurl-auth")]
910
mod lnurl_auth_jwt;
11+
12+
#[cfg(feature = "lnurl-auth")]
1013
pub use lnurl_auth_jwt::LnurlAuthJwt;
1114

1215
/// Errors around providing headers for each VSS request.

tests/lnurl_auth_jwt_tests.rs

Lines changed: 94 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,100 @@
1-
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
2-
use base64::Engine;
3-
use mockito::Matcher;
4-
use serde_json::json;
5-
use std::collections::HashMap;
6-
use std::time::SystemTime;
7-
use vss_client::headers::LnurlAuthJwt;
8-
use vss_client::headers::VssHeaderProvider;
1+
#[cfg(feature = "lnurl-auth")]
2+
mod lnurl_auth_jwt_tests {
3+
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
4+
use base64::Engine;
5+
use mockito::Matcher;
6+
use serde_json::json;
7+
use std::collections::HashMap;
8+
use std::time::SystemTime;
9+
use vss_client::headers::LnurlAuthJwt;
10+
use vss_client::headers::VssHeaderProvider;
911

10-
const APPLICATION_JSON: &'static str = "application/json";
12+
const APPLICATION_JSON: &'static str = "application/json";
1113

12-
fn lnurl_auth_response(jwt: &str) -> String {
13-
json!({
14-
"status": "OK",
15-
"token": jwt,
16-
})
17-
.to_string()
18-
}
19-
20-
fn jwt_with_expiry(exp: u64) -> String {
21-
let claims = json!({
22-
"exp": exp,
23-
})
24-
.to_string();
25-
let ignored = URL_SAFE_NO_PAD.encode("ignored");
26-
let encoded = URL_SAFE_NO_PAD.encode(claims);
27-
format!("{}.{}.{}", ignored, encoded, ignored)
28-
}
14+
fn lnurl_auth_response(jwt: &str) -> String {
15+
json!({
16+
"status": "OK",
17+
"token": jwt,
18+
})
19+
.to_string()
20+
}
2921

30-
#[tokio::test]
31-
async fn test_lnurl_auth_jwt() {
32-
// Initialize LNURL Auth JWT provider connecting to the mock server.
33-
let addr = mockito::server_address();
34-
let base_url = format!("http://localhost:{}", addr.port());
35-
let lnurl_auth_jwt = LnurlAuthJwt::new(&[0; 32], base_url.clone(), HashMap::new()).unwrap();
36-
{
37-
// First request will be provided with an expired JWT token.
38-
let k1 = "0000000000000000000000000000000000000000000000000000000000000000";
39-
let expired_jwt = jwt_with_expiry(0);
40-
let lnurl = mockito::mock("GET", "/")
41-
.expect(1)
42-
.with_status(200)
43-
.with_body(format!("{}/verify?tag=login&k1={}", base_url, k1))
44-
.create();
45-
let lnurl_verification = mockito::mock("GET", "/verify")
46-
.match_query(Matcher::AllOf(vec![
47-
Matcher::UrlEncoded("k1".into(), k1.into()),
48-
Matcher::Regex("sig=".into()),
49-
Matcher::Regex("key=".into()),
50-
]))
51-
.expect(1)
52-
.with_status(200)
53-
.with_header(reqwest::header::CONTENT_TYPE.as_str(), APPLICATION_JSON)
54-
.with_body(lnurl_auth_response(&expired_jwt))
55-
.create();
56-
assert_eq!(
57-
lnurl_auth_jwt.get_headers().await.unwrap().get("authorization").unwrap(),
58-
&format!("Bearer {}", expired_jwt),
59-
);
60-
lnurl.assert();
61-
lnurl_verification.assert();
22+
fn jwt_with_expiry(exp: u64) -> String {
23+
let claims = json!({
24+
"exp": exp,
25+
})
26+
.to_string();
27+
let ignored = URL_SAFE_NO_PAD.encode("ignored");
28+
let encoded = URL_SAFE_NO_PAD.encode(claims);
29+
format!("{}.{}.{}", ignored, encoded, ignored)
6230
}
63-
{
64-
// Second request will be provided with a non-expired JWT token.
65-
// This will be cached.
66-
let k1 = "1000000000000000000000000000000000000000000000000000000000000000";
67-
let valid_jwt = jwt_with_expiry(
68-
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs() + 60 * 60 * 24 * 365,
69-
);
70-
let lnurl = mockito::mock("GET", "/")
71-
.expect(1)
72-
.with_status(200)
73-
.with_body(format!("{}/verify?tag=login&k1={}", base_url, k1))
74-
.create();
75-
let lnurl_verification = mockito::mock("GET", "/verify")
76-
.match_query(Matcher::AllOf(vec![
77-
Matcher::UrlEncoded("k1".into(), k1.into()),
78-
Matcher::Regex("sig=".to_string()),
79-
Matcher::Regex("key=".to_string()),
80-
]))
81-
.expect(1)
82-
.with_status(200)
83-
.with_header(reqwest::header::CONTENT_TYPE.as_str(), APPLICATION_JSON)
84-
.with_body(lnurl_auth_response(&valid_jwt))
85-
.create();
86-
assert_eq!(
87-
lnurl_auth_jwt.get_headers().await.unwrap().get("authorization").unwrap(),
88-
&format!("Bearer {}", valid_jwt),
89-
);
90-
assert_eq!(
91-
lnurl_auth_jwt.get_headers().await.unwrap().get("authorization").unwrap(),
92-
&format!("Bearer {}", valid_jwt),
93-
);
94-
lnurl.assert();
95-
lnurl_verification.assert();
31+
32+
#[tokio::test]
33+
async fn test_lnurl_auth_jwt() {
34+
// Initialize LNURL Auth JWT provider connecting to the mock server.
35+
let addr = mockito::server_address();
36+
let base_url = format!("http://localhost:{}", addr.port());
37+
let lnurl_auth_jwt = LnurlAuthJwt::new(&[0; 32], base_url.clone(), HashMap::new()).unwrap();
38+
{
39+
// First request will be provided with an expired JWT token.
40+
let k1 = "0000000000000000000000000000000000000000000000000000000000000000";
41+
let expired_jwt = jwt_with_expiry(0);
42+
let lnurl = mockito::mock("GET", "/")
43+
.expect(1)
44+
.with_status(200)
45+
.with_body(format!("{}/verify?tag=login&k1={}", base_url, k1))
46+
.create();
47+
let lnurl_verification = mockito::mock("GET", "/verify")
48+
.match_query(Matcher::AllOf(vec![
49+
Matcher::UrlEncoded("k1".into(), k1.into()),
50+
Matcher::Regex("sig=".into()),
51+
Matcher::Regex("key=".into()),
52+
]))
53+
.expect(1)
54+
.with_status(200)
55+
.with_header(reqwest::header::CONTENT_TYPE.as_str(), APPLICATION_JSON)
56+
.with_body(lnurl_auth_response(&expired_jwt))
57+
.create();
58+
assert_eq!(
59+
lnurl_auth_jwt.get_headers().await.unwrap().get("authorization").unwrap(),
60+
&format!("Bearer {}", expired_jwt),
61+
);
62+
lnurl.assert();
63+
lnurl_verification.assert();
64+
}
65+
{
66+
// Second request will be provided with a non-expired JWT token.
67+
// This will be cached.
68+
let k1 = "1000000000000000000000000000000000000000000000000000000000000000";
69+
let valid_jwt = jwt_with_expiry(
70+
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs() + 60 * 60 * 24 * 365,
71+
);
72+
let lnurl = mockito::mock("GET", "/")
73+
.expect(1)
74+
.with_status(200)
75+
.with_body(format!("{}/verify?tag=login&k1={}", base_url, k1))
76+
.create();
77+
let lnurl_verification = mockito::mock("GET", "/verify")
78+
.match_query(Matcher::AllOf(vec![
79+
Matcher::UrlEncoded("k1".into(), k1.into()),
80+
Matcher::Regex("sig=".to_string()),
81+
Matcher::Regex("key=".to_string()),
82+
]))
83+
.expect(1)
84+
.with_status(200)
85+
.with_header(reqwest::header::CONTENT_TYPE.as_str(), APPLICATION_JSON)
86+
.with_body(lnurl_auth_response(&valid_jwt))
87+
.create();
88+
assert_eq!(
89+
lnurl_auth_jwt.get_headers().await.unwrap().get("authorization").unwrap(),
90+
&format!("Bearer {}", valid_jwt),
91+
);
92+
assert_eq!(
93+
lnurl_auth_jwt.get_headers().await.unwrap().get("authorization").unwrap(),
94+
&format!("Bearer {}", valid_jwt),
95+
);
96+
lnurl.assert();
97+
lnurl_verification.assert();
98+
}
9699
}
97100
}

0 commit comments

Comments
 (0)