use authkestra::flow::Engine;
use authkestra_axum::{AuthSession, AxumError, AxumExt, AxumState};
use authkestra_engine::auth::SessionStore;
use authkestra_engine::{AkWebAppEngine, SessionConfig};
use axum::{
response::{IntoResponse, Json},
routing::get,
Router,
};
use serde_json::json;
use std::sync::Arc;
use tower_cookies::CookieManagerLayer;
use tower_http::services::ServeDir;
#[derive(Clone, AxumState)]
struct AppState {
#[authkestra(engine)]
auth: AkWebAppEngine,
}
#[tokio::main]
async fn main() {
let session_store: Arc<dyn SessionStore> =
Arc::new(authkestra_engine::store::memory::MemoryStore::default());
let auth_engine = Engine::builder()
.session_store(session_store)
.session_config(SessionConfig {
secure: false, ..Default::default()
})
.build();
let state = AppState {
auth: auth_engine.clone(),
};
let app = Router::new()
.fallback_service(ServeDir::new(concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/static"
)))
.route("/api/user", get(get_user))
.merge(auth_engine.axum_router())
.layer(CookieManagerLayer::new())
.with_state(state);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
println!("🚀 Axum Basic Setup running on http://localhost:3000");
axum::serve(listener, app).await.unwrap();
}
async fn get_user(session: Result<AuthSession, AxumError>) -> impl IntoResponse {
match session {
Ok(AuthSession(session)) => Json(json!({
"id": session.identity.external_id,
"username": session.identity.username,
"email": session.identity.email,
"provider": session.identity.provider_id,
})),
Err(_) => Json(json!({ "error": "Not authenticated" })),
}
}