Basic Authentication
Middleware providing support for Basic Auth.
Introduction to Basic Auth
Basic Auth is a simple HTTP authentication mechanism that transmits username and password by including the Authorization
field in the HTTP request header. The format is Authorization: Basic <base64(username:password)>
. Although simple, because the credentials are only Base64 encoded and not encrypted, it typically needs to be used with HTTPS to ensure security.
Comparison of Basic Auth Implementations in Common Frameworks
Framework | Language | Basic Auth Implementation |
---|
Salvo | Rust | Implemented via BasicAuth middleware and custom BasicAuthValidator |
Express | JavaScript | Using the express-basic-auth middleware package |
Spring Security | Java | Implemented via httpBasic() configuration and UserDetailsService |
ASP.NET Core | C# | Using .UseAuthentication() and AddAuthentication(AuthenticationSchemes.Basic) |
Gin | Go | Via custom middleware or using the gin-contrib/auth package |
Use Cases
Basic Auth is suitable for the following scenarios:
- Internal APIs and Tools: Management tools and APIs used within a company.
- Development and Testing Environments: Quickly implement authentication without needing a complex login system.
- Simple API Protection: When a complex user management system is not required.
- In Conjunction with Other Security Measures: As part of a multi-layered security architecture.
In Salvo, the Basic Auth middleware can be easily integrated into routes. Custom validation logic can be implemented by implementing the BasicAuthValidator
trait, offering great flexibility.
Important Considerations
- Always use with HTTPS to protect credential transmission.
- Not suitable for production environments handling sensitive information.
- Consider using more secure authentication methods like JWT, OAuth, etc., for production environments.
basic-auth/src/main.rs
use salvo::basic_auth::{BasicAuth, BasicAuthValidator};
use salvo::prelude::*;
// Custom validator implementing BasicAuthValidator trait
struct Validator;
impl BasicAuthValidator for Validator {
// Validate username and password combination
async fn validate(&self, username: &str, password: &str, _depot: &mut Depot) -> bool {
username == "root" && password == "pwd"
}
}
// Simple handler that returns "Hello" for authenticated requests
#[handler]
async fn hello() -> &'static str {
"Hello"
}
// Create router with basic authentication middleware
fn route() -> Router {
// Initialize basic authentication handler with our validator
let auth_handler = BasicAuth::new(Validator);
// Apply authentication middleware to the router
Router::with_hoop(auth_handler).goal(hello)
}
#[tokio::main]
async fn main() {
// Initialize logging
tracing_subscriber::fmt().init();
// Bind server to port 5800 and start serving
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
Server::new(acceptor).serve(route()).await;
}
#[cfg(test)]
mod tests {
use salvo::prelude::*;
use salvo::test::{ResponseExt, TestClient};
#[tokio::test]
async fn test_basic_auth() {
// Create a service instance from our router for testing purposes
let service = Service::new(super::route());
// Test case 1: Verify successful authentication with valid credentials
let content = TestClient::get("http://0.0.0.0:5800/")
.basic_auth("root", Some("pwd")) // Use correct username/password
.send(&service) // Send the request to the service
.await
.take_string() // Extract response body as string
.await
.unwrap();
// Verify response contains expected "Hello" message
assert!(content.contains("Hello"));
// Test case 2: Verify authentication failure with invalid password
let content = TestClient::get("http://0.0.0.0:5800/")
.basic_auth("root", Some("pwd2")) // Use incorrect password
.send(&service) // Send the request to the service
.await
.take_string() // Extract response body as string
.await
.unwrap();
// Verify response contains "Unauthorized" error
assert!(content.contains("Unauthorized"));
}
}