pub struct JwtService { /* private fields */ }Expand description
Signs and validates JWTs. Provide this into the DI container so the framework
boundaries (boundary.rs, ws.rs) can auto-populate RequestContext::claims()
on every incoming request.
§Secret rotation
Keys live behind Rotating (an
ArcSwap): the request path pays one atomic pointer load, while
rotate_secret — typically driven by a
SecretSource watcher — swaps in a new bundle with no restart. The
previous key is retained for verification, so live tokens (≤ TTL old)
keep validating through the grace window.
Implementations§
Source§impl JwtService
impl JwtService
pub fn new(config: JwtConfig) -> Self
Sourcepub fn rotate_secret(&self, new_secret: &[u8], version: u64)
pub fn rotate_secret(&self, new_secret: &[u8], version: u64)
Hot-swap the signing secret — no restart, no token mass-invalidation.
New tokens sign with the new key immediately; tokens signed with the previous key keep verifying until natural expiry. Versions are monotonic: a stale (≤ current) version is ignored, making concurrent watchers and duplicate delivery harmless.
Sourcepub fn issue_access(&self, sub: &str, role: &str, email: &str) -> String
pub fn issue_access(&self, sub: &str, role: &str, email: &str) -> String
Issue a signed access token.
Claims: sub = user ID, role, email, type = "access", jti, iat, exp.
Sourcepub fn issue_access_with_perms(
&self,
sub: &str,
role: &str,
email: &str,
perms: &[String],
) -> String
pub fn issue_access_with_perms( &self, sub: &str, role: &str, email: &str, perms: &[String], ) -> String
Like Self::issue_access but embeds a perms claim (array of permission strings).
Use this when the app maintains a permission map so that PermissionGuard
can do a zero-latency lookup without hitting the store on each request.
Sourcepub fn issue_access_bound(
&self,
sub: &str,
role: &str,
email: &str,
perms: &[String],
tenant: Option<&str>,
) -> String
pub fn issue_access_bound( &self, sub: &str, role: &str, email: &str, perms: &[String], tenant: Option<&str>, ) -> String
Like Self::issue_access_with_perms but additionally binds the token to
a tenant via the tenant claim. TenantGuard then enforces that
requests carrying this token resolve to the same tenant — omitting or
forging the tenant header yields 403, so a suspended tenant’s users
cannot ride the fallback pool by dropping the header.
Sourcepub fn issue_refresh(&self, sub: &str) -> (String, String)
pub fn issue_refresh(&self, sub: &str) -> (String, String)
Issue a signed refresh token with a unique jti.
Claims: sub, type = "refresh", jti, iat, exp.
The jti is returned alongside the token so the caller can persist it.
Sourcepub fn decode(&self, token: &str) -> Option<Arc<Claims>>
pub fn decode(&self, token: &str) -> Option<Arc<Claims>>
Validate signature + expiry and return the decoded claims as a JSON map.
Returns None for any invalid token (expired, bad signature, malformed).
Does NOT enforce token type — use Self::decode_access at request boundaries.
Sourcepub fn decode_access(&self, token: &str) -> Option<Arc<Claims>>
pub fn decode_access(&self, token: &str) -> Option<Arc<Claims>>
Like decode but additionally requires "type" == "access".
Use this at request boundaries so refresh tokens cannot be passed as access tokens to authenticate protected routes.
Sourcepub fn validate_refresh(&self, token: &str) -> Option<(String, String)>
pub fn validate_refresh(&self, token: &str) -> Option<(String, String)>
Validate a refresh token specifically.
Returns (subject, jti) on success, None otherwise.
Callers must verify that the jti exists in their token store before
issuing a new pair.
Sourcepub fn access_ttl_secs(&self) -> u64
pub fn access_ttl_secs(&self) -> u64
Lifetime of access tokens in seconds (used in TokenResponse.expires_in).
Sourcepub fn refresh_ttl_secs(&self) -> u64
pub fn refresh_ttl_secs(&self) -> u64
Lifetime of refresh tokens (used by token store for TTL).
Auto Trait Implementations§
impl !Freeze for JwtService
impl RefUnwindSafe for JwtService
impl Send for JwtService
impl Sync for JwtService
impl Unpin for JwtService
impl UnsafeUnpin for JwtService
impl UnwindSafe for JwtService
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request