ys memos
Blog

RustのaxumでAuthGuard的な機能を実装する方法


rust

2025/06/07


httpサーバフレームワークでは、よくAuthGuardのような機能が使えることが多い。

そこで、RustのaxumでもAuthGuard的な機能を導入できるようにしてみる。


ここでは、一例として、

axum = { version = "0.7.5", features = ["macros"] }
cookie = "0.18.1"
jsonwebtoken = "9.3.0"

のバージョンで動き、認証情報はCookieにJWTが格納されているものとする。


AuthGuardと読んでいたが、ここではJWTを検証する関係上、単なるGuardではなく、User名を取得する機能も持たせることにしてみた。

jsonwebtoken::decodeは、トークンの署名検証も兼ねているとのことなので、以下のようにJWTの検証と値取得を行う。

use axum::{async_trait, extract::FromRequestParts, http::request::Parts};
use axum_extra::extract::CookieJar;

use crate::services::jwt::JwtService;

#[derive(Debug, Clone)]
pub struct AuthUser {
    pub name: String,
}

#[async_trait]
impl<S> FromRequestParts<S> for AuthUser
where
    S: Send + Sync,
{
    type Rejection = crate::error::Error; // crate::error::Errorは、クレート内に定義したAPI用Error型とする

    async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
        let jar = CookieJar::from_request_parts(parts, state)
            .await
            .map_err(|_| crate::error::Error::Unauthorized)?;
        let token = jar
            .get("token")
            .map(|c| c.value())
            .ok_or(crate::error::Error::Unauthorized)?;
        let claims = jsonwebtoken::decode::<Claims>(
            token,
            &DecodingKey::from_secret(JWT_SECRET.as_ref()), // JWT_SECRETは適切に定義されていると仮定
            &Validation::default(),
        )?;
        Ok(Self {
            name: claims.sub(),
        })
    }
}

例のように FromRequestPartsを実装しておけば、以下のようにhandlerの引数に AuthUserを追加するだけで、認証必須のhandlerを実装できる。

#[derive(Debug, Serialize)]
pub struct MeOutput {
    pub name: String,
}

#[axum::debug_handler]
async fn me(auth_user: AuthUser) -> error::Result<Json<MeOutput>> {
    Ok(Json(MeOutput {
        name: auth_user.name,
    }))
}

単なる認証ガードとして使いたい場合は、このように、 _でうければよい。jwt検証のみの AuthGuardとして、戻り値を準備しないものとして実装しても良いかもしれない。

#[axum::debug_handler]
async fn auth_check(_: AuthUser) -> error::Result<&'static str> {
    Ok("ok")
}

クレート内に準備しておけば、エンドポイントにあとから認証を追加する場合も簡単に実装できるし、ハンドラー内で認証ユーザー名を取得できるので、便利に使えそう。


関連タグを探す