Crate salvo_jwt_auth

Crate salvo_jwt_auth 

Source
Expand description

Provides JWT (JSON Web Token) authentication support for the Salvo web framework.

This crate helps you implement JWT-based authentication in your Salvo web applications. It offers flexible token extraction from various sources (headers, query parameters, cookies, etc.) and multiple decoding strategies.

§Features

  • Extract JWT tokens from multiple sources (headers, query parameters, cookies, forms)
  • Configurable token validation
  • OpenID Connect support (behind the oidc feature flag)
  • Seamless integration with Salvo’s middleware system

§Example:

use jsonwebtoken::{self, EncodingKey};
use salvo::http::{Method, StatusError};
use salvo::jwt_auth::{ConstDecoder, QueryFinder};
use salvo::prelude::*;
use serde::{Deserialize, Serialize};
use time::{Duration, OffsetDateTime};

const SECRET_KEY: &str = "YOUR_SECRET_KEY"; // In production, use a secure key management solution

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct JwtClaims {
    username: String,
    exp: i64,
}

#[tokio::main]
async fn main() {
    let auth_handler: JwtAuth<JwtClaims, _> = JwtAuth::new(ConstDecoder::from_secret(SECRET_KEY.as_bytes()))
        .finders(vec![
            // Box::new(HeaderFinder::new()),
            Box::new(QueryFinder::new("jwt_token")),
            // Box::new(CookieFinder::new("jwt_token")),
        ])
        .force_passed(true);

    let acceptor = TcpListener::new("0.0.0.0:8698").bind().await;
    Server::new(acceptor)
        .serve(Router::with_hoop(auth_handler).goal(index))
        .await;
}
#[handler]
async fn index(req: &mut Request, depot: &mut Depot, res: &mut Response) -> anyhow::Result<()> {
    if req.method() == Method::POST {
        let (username, password) = (
            req.form::<String>("username").await.unwrap_or_default(),
            req.form::<String>("password").await.unwrap_or_default(),
        );
        if !validate(&username, &password) {
            res.render(Text::Html(LOGIN_HTML));
            return Ok(());
        }
        let exp = OffsetDateTime::now_utc() + Duration::days(14);
        let claim = JwtClaims {
            username,
            exp: exp.unix_timestamp(),
        };
        let token = jsonwebtoken::encode(
            &jsonwebtoken::Header::default(),
            &claim,
            &EncodingKey::from_secret(SECRET_KEY.as_bytes()),
        )?;
        res.render(Redirect::other(format!("/?jwt_token={token}")));
    } else {
        match depot.jwt_auth_state() {
            JwtAuthState::Authorized => {
                let data = depot.jwt_auth_data::<JwtClaims>().unwrap();
                res.render(Text::Plain(format!(
                    "Hi {}, you have logged in successfully!",
                    data.claims.username
                )));
            }
            JwtAuthState::Unauthorized => {
                res.render(Text::Html(LOGIN_HTML));
            }
            JwtAuthState::Forbidden => {
                res.render(StatusError::forbidden());
            }
        }
    }
    Ok(())
}

fn validate(username: &str, password: &str) -> bool {
    // In a real application, use secure password verification
    username == "root" && password == "pwd"
}

static LOGIN_HTML: &str = r#"<!DOCTYPE html>
<html>
    <head>
        <title>JWT Auth Demo</title>
    </head>
    <body>
        <h1>JWT Auth</h1>
        <form action="/" method="post">
        <label for="username"><b>Username</b></label>
        <input type="text" placeholder="Enter Username" name="username" required>

        <label for="password"><b>Password</b></label>
        <input type="password" placeholder="Enter Password" name="password" required>

        <button type="submit">Login</button>
    </form>
    </body>
</html>
"#;

Re-exports§

pub use jsonwebtoken::Algorithm;
pub use jsonwebtoken::DecodingKey;
pub use jsonwebtoken::TokenData;
pub use jsonwebtoken::Validation;
pub use jsonwebtoken::decode;
pub use jsonwebtoken::errors::Error as JwtError;
pub use oidc::OidcDecoder;oidc

Modules§

oidcoidc
Oidc(OpenID Connect) supports.

Structs§

ConstDecoder
A decoder that uses a constant key for JWT token validation.
CookieFinder
Extracts JWT tokens from cookies.
FormFinder
Extracts JWT tokens from request form data.
HeaderFinder
Extracts JWT tokens from HTTP request headers.
JwtAuth
JWT Authentication middleware for Salvo.
QueryFinder
Extracts JWT tokens from URL query parameters.

Enums§

JwtAuthError
JwtAuthError
JwtAuthState
Possible states of JWT authentication.

Constants§

JWT_AUTH_DATA_KEY
key used to insert auth decoded data to depot.
JWT_AUTH_ERROR_KEY
key used to insert auth error to depot.
JWT_AUTH_STATE_KEY
key used to insert auth state data to depot.
JWT_AUTH_TOKEN_KEY
key used to insert auth token data to depot.

Traits§

JwtAuthDecoder
Trait for JWT token decoding and validation.
JwtAuthDepotExt
Extension trait for accessing JWT authentication data from the depot.
JwtTokenFinder
Trait for extracting JWT tokens from HTTP requests.