🪪 Session-based user authentication for Axum.
axum-login is a Tower middleware providing session-based user authentication for axum applications.
axum-sessions to provide flexible sessionstower_http::auth::RequireAuthorizationLayer to protect routesNote
axum-loginimplements a fundamental pattern for user authentication, however some features may be missing. Folks are encouraged to make suggestions for extensions to the library.
To use the crate in your project, add the following to your Cargo.toml file:
toml
[dependencies]
axum-login = "0.3.0"
axum applications can use the middleware via the auth layer.
axum Example```rust use axum::{response::IntoResponse, routing::get, Extension, Router}; use axumlogin::{ axumsessions::{async_session::MemoryStore, SessionLayer}, AuthLayer, AuthUser, RequireAuthorizationLayer, SqliteStore, }; use rand::Rng; use sqlx::sqlite::SqlitePoolOptions;
struct User { id: i64, password_hash: String, name: String, }
impl AuthUser for User { fn get_id(&self) -> String { format!("{}", self.id) }
fn get_password_hash(&self) -> String {
self.password_hash.clone()
}
}
type AuthContext = axum_login::extractors::AuthContext
async fn main() { let secret = rand::thread_rng().gen::<[u8; 64]>();
let session_store = MemoryStore::new();
let session_layer = SessionLayer::new(session_store, &secret).with_secure(false);
let pool = SqlitePoolOptions::new()
.connect("user_store.db")
.await
.unwrap();
let user_store = SqliteStore::<User>::new(pool);
let auth_layer = AuthLayer::new(user_store, &secret);
async fn login_handler(mut auth: AuthContext) {
let pool = SqlitePoolOptions::new()
.connect("user_store.db")
.await
.unwrap();
let mut conn = pool.acquire().await.unwrap();
let user: User = sqlx::query_as("select * from users where id = 1")
.fetch_one(&mut conn)
.await
.unwrap();
auth.login(&user).await.unwrap();
}
async fn logout_handler(mut auth: AuthContext) {
dbg!("Logging out user: {}", &auth.current_user);
auth.logout().await;
}
async fn protected_handler(Extension(user): Extension<User>) -> impl IntoResponse {
format!("Logged in as: {}", user.name)
}
let app = Router::new()
.route("/protected", get(protected_handler))
.route_layer(RequireAuthorizationLayer::<User>::login())
.route("/login", get(login_handler))
.route("/logout", get(logout_handler))
.layer(auth_layer)
.layer(session_layer);
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
} ```
You can find this example as well as other example projects in the example directory.
See the crate documentation for more usage information.