reth_rpc_layer/
jwt_validator.rs1use crate::{AuthValidator, JwtError, JwtSecret};
2use http::{header, HeaderMap, Response, StatusCode};
3use jsonrpsee_server::{HttpBody, HttpResponse};
4use tracing::error;
5
6#[derive(Debug, Clone)]
10pub struct JwtAuthValidator {
11 secret: JwtSecret,
12}
13
14impl JwtAuthValidator {
15 pub const fn new(secret: JwtSecret) -> Self {
19 Self { secret }
20 }
21}
22
23impl AuthValidator for JwtAuthValidator {
24 fn validate(&self, headers: &HeaderMap) -> Result<(), HttpResponse> {
25 match get_bearer(headers) {
26 Some(jwt) => match self.secret.validate(jwt) {
27 Ok(_) => Ok(()),
28 Err(e) => {
29 error!(target: "engine::jwt-validator", "Invalid JWT: {e}");
30 let response = err_response(e);
31 Err(response)
32 }
33 },
34 None => {
35 let e = JwtError::MissingOrInvalidAuthorizationHeader;
36 error!(target: "engine::jwt-validator", "Invalid JWT: {e}");
37 let response = err_response(e);
38 Err(response)
39 }
40 }
41 }
42}
43
44fn get_bearer(headers: &HeaderMap) -> Option<&str> {
47 headers.get(header::AUTHORIZATION)?.to_str().ok()?.strip_prefix("Bearer ")
48}
49
50fn err_response(err: JwtError) -> HttpResponse {
51 Response::builder()
55 .status(StatusCode::UNAUTHORIZED)
56 .body(HttpBody::new(err.to_string()))
57 .expect("This should never happen")
58}
59
60#[cfg(test)]
61mod tests {
62 use crate::jwt_validator::get_bearer;
63 use http::{header, HeaderMap};
64
65 #[test]
66 fn auth_header_available() {
67 let jwt = "foo";
68 let bearer = format!("Bearer {jwt}");
69 let mut headers = HeaderMap::new();
70 headers.insert(header::AUTHORIZATION, bearer.parse().unwrap());
71 let token = get_bearer(&headers).unwrap();
72 assert_eq!(token, jwt);
73 assert_eq!(
74 token.as_ptr(),
75 headers[header::AUTHORIZATION].as_bytes()[bearer.len() - jwt.len()..].as_ptr()
76 );
77 }
78
79 #[test]
80 fn auth_header_not_available() {
81 let headers = HeaderMap::new();
82 let token = get_bearer(&headers);
83 assert!(token.is_none());
84 }
85
86 #[test]
87 fn auth_header_malformed() {
88 let jwt = "foo";
89 let bearer = format!("Bea___rer {jwt}");
90 let mut headers = HeaderMap::new();
91 headers.insert(header::AUTHORIZATION, bearer.parse().unwrap());
92 let token = get_bearer(&headers);
93 assert!(token.is_none());
94 }
95
96 #[test]
97 fn auth_header_bearer_in_middle() {
98 let jwt = "valid_token";
100 let bearer = format!("NotBearer Bearer {jwt}");
101 let mut headers = HeaderMap::new();
102 headers.insert(header::AUTHORIZATION, bearer.parse().unwrap());
103 let token = get_bearer(&headers);
104 assert!(token.is_none());
106 }
107
108 #[test]
109 fn auth_header_bearer_without_space() {
110 let jwt = "valid_token";
112 let bearer = format!("BearerBearer {jwt}");
113 let mut headers = HeaderMap::new();
114 headers.insert(header::AUTHORIZATION, bearer.parse().unwrap());
115 let token = get_bearer(&headers);
116 assert!(token.is_none());
118 }
119}