rust
50 lines · 8 steps
Signed cookie sessions in Axum
Build login, identity, and logout handlers backed by tamper-proof signed cookies in Axum.
Explained by
highlit
1use axum::{
2 extract::FromRef,
3 http::StatusCode,
4 response::{IntoResponse, Redirect},
5 Form,
6};
7use axum_extra::extract::cookie::{Cookie, Key, SignedCookieJar};
8use serde::Deserialize;
9use time::Duration;
10
11#[derive(Clone)]
12struct AppState {
13 cookie_key: Key,
14}
15
16impl FromRef<AppState> for Key {
17 fn from_ref(state: &AppState) -> Self {
18 state.cookie_key.clone()
19 }
20}
21
22#[derive(Deserialize)]
23struct Login {
24 user_id: String,
25}
26
27async fn create_session(
28 jar: SignedCookieJar,
29 Form(login): Form<Login>,
30) -> impl IntoResponse {
31 let cookie = Cookie::build(("session_user", login.user_id))
32 .path("/")
33 .http_only(true)
34 .secure(true)
35 .same_site(axum_extra::extract::cookie::SameSite::Lax)
36 .max_age(Duration::days(7));
37
38 (jar.add(cookie), Redirect::to("/dashboard"))
39}
40
41async fn current_user(jar: SignedCookieJar) -> Result<String, StatusCode> {
42 match jar.get("session_user") {
43 Some(cookie) => Ok(format!("Logged in as {}", cookie.value())),
44 None => Err(StatusCode::UNAUTHORIZED),
45 }
46}
47
48async fn logout(jar: SignedCookieJar) -> impl IntoResponse {
49 (jar.remove(Cookie::from("session_user")), Redirect::to("/"))
50}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1A signing key in shared state lets Axum verify cookies haven't been tampered with on every request.
- 2Setting http_only, secure, and same_site hardens session cookies against XSS and CSRF leakage.
- 3Returning a tuple of jar plus response lets a handler mutate cookies and redirect in one expression.
Related explainers
rust
use axum::{extract::{Path, State}, http::StatusCode, Json}; use dashmap::DashMap; use serde::Serialize; use std::sync::Arc;
Request coalescing in an Axum handler
caching
concurrency
request-coalescing
Advanced
8 steps
rust
use std::net::Ipv4Addr; use std::str::FromStr; #[derive(Debug, Clone, Copy)]
Parsing and matching IPv4 CIDR ranges in Rust
bitwise-operations
parsing
error-handling
Intermediate
8 steps
php
<?php namespace App\Http\Middleware;
Resolving the current team in Laravel middleware
middleware
multi-tenancy
cookies
Intermediate
8 steps
rust
use std::sync::OnceLock; static CRC_TABLE: OnceLock<[u32; 256]> = OnceLock::new();
Table-driven CRC32 with lazy init in Rust
checksums
lazy-initialization
lookup-tables
Intermediate
8 steps
rust
use axum::{ body::Body, extract::Path, http::{header, HeaderMap, HeaderValue, StatusCode},
HTTP range requests for video streaming in Axum
http-range-requests
streaming
async-io
Advanced
8 steps
rust
use std::sync::mpsc; use std::thread; use std::time::Duration;
Running work with a timeout in Rust
concurrency
channels
timeout
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/signed-cookie-sessions-in-axum-explained-rust-0dfa/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.