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が格納されているものとする。
AuthUser
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")
}
おわりに
クレート内に準備しておけば、エンドポイントにあとから認証を追加する場合も簡単に実装できるし、ハンドラー内で認証ユーザー名を取得できるので、便利に使えそう。