Expand description
Authfix provides a quick and easy way to add authentication to your Actix Web app.
The AuthToken extractor enables straightforward access to the authenticated user in secured handlers.
§Quick start
For a quick start, use the working examples from authfix-examples
§Session Authentication
Currently, only session authentication is supported (OIDC support is planned). This implementation is built on actix-session. Authfix re-exports actix-session for this reason.
The session authentication flow can be configured in two modes.
- API based (default)
- It is designed to work with Single Page Applications, so it offers a JSON API for login, logout and mfa verification. Redirects are then handled by the SPA.
- Redirect based
- Instead of returning 401 for unauthorized requests, it redirects the user to the login page. The login flow is completely handled by the browser.
You just have to define the login, mfa and logout pages. The redirects are going to the same routes as defined in Routes.
To activate this mode, set
with_redirect_flow()
in SessionLoginAppBuilder.
- Instead of returning 401 for unauthorized requests, it redirects the user to the login page. The login flow is completely handled by the browser.
You just have to define the login, mfa and logout pages. The redirects are going to the same routes as defined in Routes.
To activate this mode, set
§Async traits
To use this library, it is necessary to implement certrain traits (e.g.: LoadUserByCredentials). Wherever possible, native async syntax is supported.
However, some of the traits must be dyn compatible
, so the async_trait crate
is used for those (e.g. for MfaHandleMfaRequest).
Authfix re-exports the authfix::async_trait macro.
§Examples
§Session based authentication
use actix_web::{HttpResponse, HttpServer, Responder, cookie::Key, get};
use authfix::{
AuthToken,
login::{LoadUserByCredentials, LoadUserError, LoginToken},
session::{AccountInfo, app_builder::SessionLoginAppBuilder},
};
use serde::{Deserialize, Serialize};
// A user intended for session authentication must derive Serialize, and Deserialize.
#[derive(Serialize, Deserialize)]
struct User {
name: String,
}
// AccountInfo trait is used for disabling the user or to lock the account
// The user is enabled by default
impl AccountInfo for User {}
// Struct that handles the authentication
struct AuthenticationService;
// LoadUsersByCredentials uses async_trait, so its needed when implementing the trait for AuthenticationService
// async_trait is re-exported by authfix.
impl LoadUserByCredentials for AuthenticationService {
type User = User;
async fn load_user(&self, login_token: &LoginToken) -> Result<Self::User, LoadUserError> {
// load user by email logic and check password
// currently authfix does not provide hashing functions, you can use for example https://docs.rs/argon2/latest/argon2/
if login_token.email == "test@example.org" && login_token.password == "password" {
Ok(User {
name: "Johnny".to_owned(),
})
} else {
Err(LoadUserError::LoginFailed)
}
}
}
// You have access to the user via the AuthToken extractor in secured routes.
#[get("/secured")]
async fn secured(auth_token: AuthToken<User>) -> impl Responder {
let user = auth_token.authenticated_user();
HttpResponse::Ok().json(&*user)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let key = Key::generate();
HttpServer::new(move || {
// SessionLoginAppBuilder is the simplest way to create an App instance configured with session based authentication
// This default config registers handlers for: /login, /logout and /login/mfa.
SessionLoginAppBuilder::create(AuthenticationService, key.clone())
.build()
.service(secured)
})
.bind("127.0.0.1:7080")?
.run()
.await
}
§Configure the session
use actix_web::{HttpResponse, HttpServer, Responder, cookie::Key, get, middleware::Logger};
use authfix::{
AuthToken,
login::{LoadUserByCredentials, LoadUserError, LoginToken},
session::{
AccountInfo,
actix_session::{
SessionMiddleware,
config::{PersistentSession, SessionLifecycle},
storage::CookieSessionStore,
},
app_builder::SessionLoginAppBuilder,
},
};
use serde::{Deserialize, Serialize};
// A user intended for session authentication must derive or implement Serialize, and Deserialize.
#[derive(Serialize, Deserialize)]
struct User {
name: String,
}
impl AccountInfo for User {}
// Struct that handles the authentication
struct AuthenticationService;
// LoadUsersByCredentials uses async_trait, so its needed when implementing the trait for AuthenticationService
// async_trait is re-exported by authfix.
impl LoadUserByCredentials for AuthenticationService {
type User = User;
async fn load_user(&self, login_token: &LoginToken) -> Result<Self::User, LoadUserError> {
// load user by email logic and check password
// currently authfix does not provide hashing functions, you can use for example https://docs.rs/argon2/latest/argon2/
if login_token.email == "test@example.org" && login_token.password == "password" {
Ok(User {
name: "Johnny".to_owned(),
})
} else {
Err(LoadUserError::LoginFailed)
}
}
}
// You have access to the user via the AuthToken extractor in secured routes.
#[get("/secured")]
async fn secured(auth_token: AuthToken<User>) -> impl Responder {
let user = auth_token.authenticated_user();
HttpResponse::Ok().json(&*user)
}
pub fn session_config(key: Key) -> SessionMiddleware<CookieSessionStore> {
let persistent_session = PersistentSession::default();
let lc = SessionLifecycle::PersistentSession(persistent_session);
SessionMiddleware::builder(CookieSessionStore::default(), key)
.cookie_name("sessionId".to_string())
.cookie_http_only(true)
.cookie_same_site(actix_web::cookie::SameSite::Strict)
.cookie_secure(false)
.session_lifecycle(lc)
.build()
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let key = Key::generate();
HttpServer::new(move || {
// SessionLoginAppBuilder is the simplest way to create an App instance configured with session based authentication
SessionLoginAppBuilder::create_with_session_middleware(
AuthenticationService,
session_config(key.clone()),
)
// create App instance with build()
.build()
.wrap(Logger::default())
.service(secured)
})
.bind("127.0.0.1:7080")?
.run()
.await
}
Modules§
- errors
- Error types for all kinds of authentication
- login
- middleware
- multifactor
- session
Structs§
- Auth
Token - Extractor that holds the authenticated user.
Traits§
- Auth
Token Ext - Extension to get the AuthToken from HttpRequest
- Authentication
Provider - Main component used by the middleware to handle the actual authentication mechanism
Attribute Macros§
- async_
trait - Re-exported
async_trait
macro for use in trait definitions.