Authkestra

Quick Start

Build your first auth flow with Authkestra and Axum.

This guide walks you through building a simple web application using Axum and GitHub OAuth authentication, powered by Authkestra.

Step 1: Dependencies

Add the following to your Cargo.toml. We'll use the axum, github, and macros features of authkestra.

Cargo.toml
[dependencies]
authkestra = { version = "0.1.2", features = ["axum", "github", "macros"] }
axum = "0.8.8"
tokio = { version = "1", features = ["full"] }
tower-cookies = "0.11.0"
dotenvy = "0.15"

Step 2: Configuration

To start, configure the GithubProvider with your credentials and initialize the Authkestra instance using the builder pattern.

// Load credentials from environment
let client_id = std::env::var("GITHUB_CLIENT_ID").expect("GITHUB_CLIENT_ID must be set");
let client_secret = std::env::var("GITHUB_CLIENT_SECRET").expect("GITHUB_CLIENT_SECRET must be set");
let redirect_uri = "http://localhost:3000/auth/github/callback".to_string();

// Initialize the provider and Authkestra
let provider = GithubProvider::new(client_id, client_secret, redirect_uri);
let authkestra = Authkestra::builder()
    .provider(OAuth2Flow::new(provider))
    .build();

Step 3: State Management

Authkestra uses Axum's state management to share authentication logic across handlers. The easiest way is to use the AuthkestraFromRef macro, which automatically generates all required trait implementations.

use authkestra_axum::AuthkestraFromRef;

#[derive(Clone, AuthkestraFromRef)]
struct AppState {
    #[authkestra]
    auth: Authkestra,
}

The macro generates all the necessary FromRef implementations that allow Authkestra's extractors (like AuthSession) to work with your custom state. Alternatively, you can use AuthkestraState directly if you don't need custom state.

Step 4: Routes

Register the Authkestra routes into your Axum router. This automatically handles the OAuth callback and logout endpoints.

let state = AppState { auth: authkestra };

let app = Router::new()
    .route("/", get(index))
    .route("/protected", get(protected))
    .merge(state.auth.axum_router()) // Registers /auth/:provider/login, /auth/:provider/callback, etc.
    .layer(CookieManagerLayer::new())
    .with_state(state);

Step 5: Handlers

Use the AuthSession extractor to protect your routes. It provides access to the authenticated user's identity.

async fn index() -> impl IntoResponse {
    Html(r#"<a href="/auth/github?success_url=/protected">Login with GitHub</a>"#)
}

async fn protected(AuthSession(session): AuthSession) -> impl IntoResponse {
    format!(
        "Hello, {}! Your email is {:?}. Provider: {}.",
        session.identity.username.unwrap_or_default(),
        session.identity.email,
        session.identity.provider_id,
    )
}

Conclusion

You now have a functional GitHub OAuth flow in Axum!

For a complete working implementation including environment variable handling and multiple providers, check out the axum_oauth.rs example in the repository.

On this page