1
0
mirror of https://github.com/actix/actix-extras.git synced 2025-02-09 05:15:37 +01:00

166 lines
4.6 KiB
Rust
Raw Normal View History

2021-03-23 05:05:03 +00:00
//! Opinionated request identity service for Actix Web apps.
2019-03-09 18:04:40 -08:00
//!
2021-03-23 05:05:03 +00:00
//! [`IdentityService`] middleware can be used with different policies types to store
//! identity information.
2019-03-09 18:04:40 -08:00
//!
2021-03-23 05:05:03 +00:00
//! A cookie based policy is provided. [`CookieIdentityPolicy`] uses cookies as identity storage.
2019-03-09 18:04:40 -08:00
//!
2021-03-23 05:05:03 +00:00
//! To access current request identity, use the [`Identity`] extractor.
2019-03-09 18:04:40 -08:00
//!
//! ```no_run
2019-03-09 18:04:40 -08:00
//! use actix_web::*;
2019-06-12 15:52:48 +06:00
//! use actix_identity::{Identity, CookieIdentityPolicy, IdentityService};
2019-03-09 18:04:40 -08:00
//!
2021-03-23 05:05:03 +00:00
//! #[get("/")]
2019-11-22 11:49:35 +06:00
//! async fn index(id: Identity) -> String {
2019-03-09 18:04:40 -08:00
//! // access request identity
2019-03-09 20:40:09 -08:00
//! if let Some(id) = id.identity() {
//! format!("Welcome! {}", id)
2019-03-09 18:04:40 -08:00
//! } else {
2019-03-09 20:40:09 -08:00
//! "Welcome Anonymous!".to_owned()
2019-03-09 18:04:40 -08:00
//! }
//! }
//!
2021-03-23 05:05:03 +00:00
//! #[post("/login")]
2019-11-22 11:49:35 +06:00
//! async fn login(id: Identity) -> HttpResponse {
2019-03-09 20:40:09 -08:00
//! id.remember("User1".to_owned()); // <- remember identity
2019-03-09 18:04:40 -08:00
//! HttpResponse::Ok().finish()
//! }
//!
2021-03-23 05:05:03 +00:00
//! #[post("/logout")]
2019-11-22 11:49:35 +06:00
//! async fn logout(id: Identity) -> HttpResponse {
2019-03-09 20:40:09 -08:00
//! id.forget(); // <- remove identity
2019-03-09 18:04:40 -08:00
//! HttpResponse::Ok().finish()
//! }
//!
//! #[actix_web::main]
//! async fn main() -> std::io::Result<()> {
//! HttpServer::new(move || {
//! // create cookie identity backend
//! let policy = CookieIdentityPolicy::new(&[0; 32])
//! .name("auth-cookie")
//! .secure(false);
//!
//! App::new()
//! // wrap policy into middleware identity middleware
//! .wrap(IdentityService::new(policy))
//! .service(services![index, login, logout])
//! })
//! .bind(("0.0.0.0", 8080u16))?
//! .run()
//! .await
//! }
2019-03-09 18:04:40 -08:00
//! ```
2020-07-06 15:47:22 +09:00
2021-03-23 05:05:03 +00:00
#![deny(rust_2018_idioms, nonstandard_style)]
2021-12-08 06:11:13 +00:00
#![warn(future_incompatible)]
2020-07-06 15:47:22 +09:00
2021-03-23 05:05:03 +00:00
use std::future::Future;
2019-03-09 18:04:40 -08:00
2021-03-23 05:05:03 +00:00
use actix_web::{
dev::{ServiceRequest, ServiceResponse},
Error, HttpMessage, Result,
};
2019-03-09 18:04:40 -08:00
2021-03-23 05:05:03 +00:00
mod cookie;
mod identity;
mod middleware;
2019-03-09 18:04:40 -08:00
2021-03-23 05:05:03 +00:00
pub use self::cookie::CookieIdentityPolicy;
pub use self::identity::Identity;
pub use self::middleware::IdentityService;
2019-03-09 20:40:09 -08:00
2021-03-23 05:05:03 +00:00
/// Identity policy.
2019-03-09 20:40:09 -08:00
pub trait IdentityPolicy: Sized + 'static {
/// The return type of the middleware
2019-11-21 10:31:52 +06:00
type Future: Future<Output = Result<Option<String>, Error>>;
2019-03-09 18:04:40 -08:00
/// The return type of the middleware
2019-11-21 10:31:52 +06:00
type ResponseFuture: Future<Output = Result<(), Error>>;
2019-03-09 18:04:40 -08:00
/// Parse the session from request and load data from a service identity.
2021-03-23 05:05:03 +00:00
fn from_request(&self, req: &mut ServiceRequest) -> Self::Future;
2019-03-09 20:40:09 -08:00
/// Write changes to response
fn to_response<B>(
&self,
identity: Option<String>,
changed: bool,
response: &mut ServiceResponse<B>,
) -> Self::ResponseFuture;
2019-03-09 18:04:40 -08:00
}
2021-03-23 05:05:03 +00:00
/// Helper trait that allows to get Identity.
2019-03-09 18:04:40 -08:00
///
2021-03-23 05:05:03 +00:00
/// It could be used in middleware but identity policy must be set before any other middleware that
/// needs identity. RequestIdentity is implemented both for `ServiceRequest` and `HttpRequest`.
pub trait RequestIdentity {
fn get_identity(&self) -> Option<String>;
}
2021-03-23 05:05:03 +00:00
impl<T> RequestIdentity for T
2019-03-09 20:40:09 -08:00
where
2021-03-23 05:05:03 +00:00
T: HttpMessage,
2019-03-09 20:40:09 -08:00
{
2021-03-23 05:05:03 +00:00
fn get_identity(&self) -> Option<String> {
Identity::get_identity(&self.extensions())
2019-03-09 18:04:40 -08:00
}
}
2019-03-10 17:10:41 -07:00
#[cfg(test)]
mod tests {
2021-03-23 05:05:03 +00:00
use std::time::SystemTime;
2021-12-11 16:05:21 +00:00
use actix_web::{
body::{BoxBody, EitherBody},
dev::ServiceResponse,
test, web, App, Error,
};
2019-11-26 11:25:50 +06:00
2021-03-23 05:05:03 +00:00
use super::*;
2021-03-23 05:05:03 +00:00
pub(crate) const COOKIE_KEY_MASTER: [u8; 32] = [0; 32];
pub(crate) const COOKIE_NAME: &str = "actix_auth";
pub(crate) const COOKIE_LOGIN: &str = "test";
2021-03-23 05:05:03 +00:00
#[allow(clippy::enum_variant_names)]
pub(crate) enum LoginTimestampCheck {
NoTimestamp,
NewTimestamp,
OldTimestamp(SystemTime),
}
2021-03-23 05:05:03 +00:00
#[allow(clippy::enum_variant_names)]
pub(crate) enum VisitTimeStampCheck {
NoTimestamp,
NewTimestamp,
}
2021-03-23 05:05:03 +00:00
pub(crate) async fn create_identity_server<
2019-04-24 15:29:15 -07:00
F: Fn(CookieIdentityPolicy) -> CookieIdentityPolicy + Sync + Send + Clone + 'static,
>(
f: F,
) -> impl actix_service::Service<
2021-03-21 23:50:26 +01:00
actix_http::Request,
2021-12-11 16:05:21 +00:00
Response = ServiceResponse<EitherBody<BoxBody>>,
2019-06-12 15:52:48 +06:00
Error = Error,
2019-04-24 15:29:15 -07:00
> {
test::init_service(
App::new()
2019-04-24 15:29:15 -07:00
.wrap(IdentityService::new(f(CookieIdentityPolicy::new(
&COOKIE_KEY_MASTER,
)
.secure(false)
.name(COOKIE_NAME))))
2020-07-06 15:47:22 +09:00
.service(web::resource("/").to(|id: Identity| async move {
let identity = id.identity();
if identity.is_none() {
id.remember(COOKIE_LOGIN.to_string())
}
2020-07-06 15:47:22 +09:00
web::Json(identity)
2019-04-24 15:29:15 -07:00
})),
)
2019-11-21 10:31:52 +06:00
.await
}
2019-03-10 17:10:41 -07:00
}