reth_rpc_layer/
jwt_validator.rs1use crate::{AuthValidator, JwtError, JwtSecret};
2use http::{header, HeaderMap, Response, StatusCode};
3use jsonrpsee_http_client::{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<String> {
47 let header = headers.get(header::AUTHORIZATION)?;
48 let auth: &str = header.to_str().ok()?;
49 let prefix = "Bearer ";
50
51 if !auth.starts_with(prefix) {
52 return None;
53 }
54
55 let token: &str = &auth[prefix.len()..];
56 Some(token.into())
57}
58
59fn err_response(err: JwtError) -> HttpResponse {
60 Response::builder()
64 .status(StatusCode::UNAUTHORIZED)
65 .body(HttpBody::new(err.to_string()))
66 .expect("This should never happen")
67}
68
69#[cfg(test)]
70mod tests {
71 use crate::jwt_validator::get_bearer;
72 use http::{header, HeaderMap};
73
74 #[test]
75 fn auth_header_available() {
76 let jwt = "foo";
77 let bearer = format!("Bearer {jwt}");
78 let mut headers = HeaderMap::new();
79 headers.insert(header::AUTHORIZATION, bearer.parse().unwrap());
80 let token = get_bearer(&headers).unwrap();
81 assert_eq!(token, jwt);
82 }
83
84 #[test]
85 fn auth_header_not_available() {
86 let headers = HeaderMap::new();
87 let token = get_bearer(&headers);
88 assert!(token.is_none());
89 }
90
91 #[test]
92 fn auth_header_malformed() {
93 let jwt = "foo";
94 let bearer = format!("Bea___rer {jwt}");
95 let mut headers = HeaderMap::new();
96 headers.insert(header::AUTHORIZATION, bearer.parse().unwrap());
97 let token = get_bearer(&headers);
98 assert!(token.is_none());
99 }
100
101 #[test]
102 fn auth_header_bearer_in_middle() {
103 let jwt = "valid_token";
105 let bearer = format!("NotBearer Bearer {jwt}");
106 let mut headers = HeaderMap::new();
107 headers.insert(header::AUTHORIZATION, bearer.parse().unwrap());
108 let token = get_bearer(&headers);
109 assert!(token.is_none());
111 }
112
113 #[test]
114 fn auth_header_bearer_without_space() {
115 let jwt = "valid_token";
117 let bearer = format!("BearerBearer {jwt}");
118 let mut headers = HeaderMap::new();
119 headers.insert(header::AUTHORIZATION, bearer.parse().unwrap());
120 let token = get_bearer(&headers);
121 assert!(token.is_none());
123 }
124}