oswilno/crates/actix-jwt-session/tests/ensure_redis_flow.rs

149 lines
3.9 KiB
Rust
Raw Normal View History

2023-08-14 07:38:37 +02:00
use std::sync::Arc;
2023-08-18 21:52:30 +02:00
use actix_jwt_session::{
2023-08-24 16:26:10 +02:00
Authenticated, HeaderExtractor, RedisMiddlewareFactory, SessionStorage, JWT_HEADER_NAME,
2023-08-18 21:52:30 +02:00
};
2023-08-14 07:38:37 +02:00
use actix_web::http::StatusCode;
2023-08-14 12:30:32 +02:00
use actix_web::web::{Data, Json};
2023-08-14 07:38:37 +02:00
use actix_web::HttpResponse;
2023-08-14 12:30:32 +02:00
use actix_web::{get, post};
2023-08-14 07:38:37 +02:00
use actix_web::{http::header::ContentType, test, App};
use jsonwebtoken::*;
use ring::rand::SystemRandom;
use ring::signature::{Ed25519KeyPair, KeyPair};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
struct Claims {
id: Uuid,
2023-08-17 08:07:11 +02:00
subject: String,
2023-08-14 07:38:37 +02:00
}
impl actix_jwt_session::Claims for Claims {
fn jti(&self) -> Uuid {
self.id
}
2023-08-17 08:07:11 +02:00
fn subject(&self) -> &str {
&self.subject
}
2023-08-14 07:38:37 +02:00
}
#[tokio::test(flavor = "multi_thread")]
async fn not_authenticated() {
let redis = {
use redis_async_pool::{RedisConnectionManager, RedisPool};
RedisPool::new(
RedisConnectionManager::new(
redis::Client::open("redis://localhost:6379").expect("Fail to connect to redis"),
true,
None,
),
5,
)
};
let keys = JwtSigningKeys::generate().unwrap();
let factory = RedisMiddlewareFactory::<Claims>::new(
2023-08-14 12:30:32 +02:00
Arc::new(keys.encoding_key),
2023-08-14 07:38:37 +02:00
Arc::new(keys.decoding_key),
2023-08-14 12:30:32 +02:00
Algorithm::EdDSA,
redis.clone(),
2023-08-24 16:26:10 +02:00
vec![Box::new(HeaderExtractor::new(JWT_HEADER_NAME))],
2023-08-14 07:38:37 +02:00
);
let app = App::new()
2023-08-17 20:50:27 +02:00
.app_data(Data::new(factory.storage()))
2023-08-14 07:38:37 +02:00
.wrap(factory.clone())
.app_data(Data::new(redis.clone()))
.service(sign_in)
.service(sign_out)
.service(session)
.service(root);
let app = actix_web::test::init_service(app).await;
2023-08-14 12:30:32 +02:00
let res = test::call_service(
&app,
test::TestRequest::default()
.insert_header(ContentType::plaintext())
.to_request(),
)
.await;
2023-08-14 07:38:37 +02:00
assert!(res.status().is_success());
2023-08-14 12:30:32 +02:00
let res = test::call_service(
&app,
test::TestRequest::default()
.uri("/s")
.insert_header(ContentType::plaintext())
.to_request(),
)
.await;
assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
2023-08-18 21:52:30 +02:00
let origina_claims = Claims {
id: Uuid::new_v4(),
subject: "foo".to_string(),
};
2023-08-14 12:30:32 +02:00
let res = test::call_service(
&app,
test::TestRequest::default()
.uri("/in")
.method(actix_web::http::Method::POST)
.insert_header(ContentType::json())
.set_json(&origina_claims)
.to_request(),
)
.await;
assert_eq!(res.status(), StatusCode::OK);
2023-08-14 07:38:37 +02:00
}
2023-08-14 12:30:32 +02:00
#[post("/in")]
async fn sign_in(
2023-08-17 20:50:27 +02:00
store: Data<SessionStorage<Claims>>,
2023-08-14 12:30:32 +02:00
claims: Json<Claims>,
) -> Result<HttpResponse, actix_web::Error> {
let claims = claims.into_inner();
let store = store.into_inner();
store
.clone()
.set_by_jti(claims, std::time::Duration::from_secs(300))
.await
.unwrap();
Ok(HttpResponse::Ok().body(""))
2023-08-14 07:38:37 +02:00
}
2023-08-14 12:30:32 +02:00
#[post("/out")]
2023-08-17 20:50:27 +02:00
async fn sign_out(_store: Data<SessionStorage<Claims>>) -> HttpResponse {
2023-08-14 07:38:37 +02:00
HttpResponse::Ok().body("")
}
#[get("/s")]
async fn session(auth: Authenticated<Claims>) -> HttpResponse {
HttpResponse::Ok().json(&*auth)
}
#[get("/")]
async fn root() -> HttpResponse {
HttpResponse::Ok().body("")
}
pub struct JwtSigningKeys {
encoding_key: EncodingKey,
decoding_key: DecodingKey,
}
impl JwtSigningKeys {
fn generate() -> Result<Self, Box<dyn std::error::Error>> {
let doc = Ed25519KeyPair::generate_pkcs8(&SystemRandom::new())?;
let keypair = Ed25519KeyPair::from_pkcs8(doc.as_ref())?;
let encoding_key = EncodingKey::from_ed_der(doc.as_ref());
let decoding_key = DecodingKey::from_ed_der(keypair.public_key().as_ref());
Ok(JwtSigningKeys {
encoding_key,
decoding_key,
})
}
}