use axum::{response::Html, routing::get, Router}; use sf_auth_middleware_axum::{create_auth_callback, SfAuthLayer, SfUser}; use tower_sessions::{MemoryStore, SessionManagerLayer}; #[tokio::main] async fn main() { // Set up tracing for debugging tracing_subscriber::fmt::init(); // Set up session store using in-memory storage // In production, you'd want to use a persistent store like Redis or PostgreSQL let session_store = MemoryStore::default(); let session_layer = SessionManagerLayer::new(session_store); // Build the application router let app = Router::new() // Public route - no authentication required .route("/", get(home)) // Authentication callback route - must be publicly accessible // This is where the SF auth server redirects users after authentication // After validation, users will be redirected to /dashboard .route("/auth/callback", get(create_auth_callback("/dashboard"))) // Protected routes - require authentication .route("/dashboard", get(dashboard)) .route("/profile", get(profile)) // Apply authentication middleware // The redirect URI should point to the callback route in your app // This is where the SF auth server will send users after they authenticate .layer(SfAuthLayer::new(|_req| { // Point to the auth callback route defined above "http://localhost:3000/auth/callback".to_string() })) // Apply session layer (must be after the routes) .layer(session_layer); // Start the server let listener = tokio::net::TcpListener::bind("0.0.0.0:3000") .await .unwrap(); println!("Server running on http://localhost:3000"); println!("Try accessing:"); println!(" - http://localhost:3000/ (public)"); println!(" - http://localhost:3000/dashboard (protected, will redirect to SF auth)"); println!(" - http://localhost:3000/profile (protected, will redirect to SF auth)"); println!(); println!("Authentication flow:"); println!(" 1. Access /dashboard (protected)"); println!(" 2. Redirect to SF auth with redirect_uri=http://localhost:3000/auth/callback"); println!(" 3. SF auth validates and redirects to /auth/callback with credentials"); println!(" 4. Callback validates credentials and redirects to /dashboard"); println!(" 5. Access granted to /dashboard"); axum::serve(listener, app).await.unwrap(); } /// Public home page async fn home() -> Html<&'static str> { Html( r#"
This is a public page that anyone can access.
Try accessing protected pages:
Go to Dashboard (Protected) Go to Profile (Protected)When you try to access a protected page, you'll be redirected to the SnazzyFellas authentication server.
"#, ) } /// Protected dashboard page async fn dashboard(user: SfUser) -> HtmlID: {}
This is your protected profile page.