reth_rpc_layer/
auth_client_layer.rs

1use crate::{Claims, JwtSecret};
2use http::{header::AUTHORIZATION, HeaderValue};
3use std::{
4    task::{Context, Poll},
5    time::{Duration, SystemTime, UNIX_EPOCH},
6};
7use tower::{Layer, Service};
8
9/// A layer that adds a new JWT token to every request using `AuthClientService`.
10#[derive(Debug)]
11pub struct AuthClientLayer {
12    secret: JwtSecret,
13}
14
15impl AuthClientLayer {
16    /// Create a new `AuthClientLayer` with the given `secret`.
17    pub const fn new(secret: JwtSecret) -> Self {
18        Self { secret }
19    }
20}
21
22impl<S> Layer<S> for AuthClientLayer {
23    type Service = AuthClientService<S>;
24
25    fn layer(&self, inner: S) -> Self::Service {
26        AuthClientService::new(self.secret, inner)
27    }
28}
29
30/// Automatically authenticates every client request with the given `secret`.
31#[derive(Debug, Clone)]
32pub struct AuthClientService<S> {
33    secret: JwtSecret,
34    inner: S,
35}
36
37impl<S> AuthClientService<S> {
38    const fn new(secret: JwtSecret, inner: S) -> Self {
39        Self { secret, inner }
40    }
41}
42
43impl<S, B> Service<http::Request<B>> for AuthClientService<S>
44where
45    S: Service<http::Request<B>>,
46{
47    type Response = S::Response;
48    type Error = S::Error;
49    type Future = S::Future;
50
51    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
52        self.inner.poll_ready(cx)
53    }
54
55    fn call(&mut self, mut request: http::Request<B>) -> Self::Future {
56        request.headers_mut().insert(AUTHORIZATION, secret_to_bearer_header(&self.secret));
57        self.inner.call(request)
58    }
59}
60
61/// Helper function to convert a secret into a Bearer auth header value with claims according to
62/// <https://github.com/ethereum/execution-apis/blob/main/src/engine/authentication.md#jwt-claims>.
63/// The token is valid for 60 seconds.
64pub fn secret_to_bearer_header(secret: &JwtSecret) -> HeaderValue {
65    format!(
66        "Bearer {}",
67        secret
68            .encode(&Claims {
69                iat: (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() +
70                    Duration::from_secs(60))
71                .as_secs(),
72                exp: None,
73            })
74            .unwrap()
75    )
76    .parse()
77    .unwrap()
78}