use async_trait::async_trait;
use serde_json::Value;
use super::error::AuthError;
#[async_trait]
pub trait SessionClient: Send + Sync + 'static {
async fn to_session(
&self,
cookie: Option<&str>,
token: Option<&str>,
) -> Result<Value, AuthError>;
}
#[derive(Debug, Clone)]
pub struct IdentityMapping {
pub tenant_id: String,
pub identity_id: String,
}
#[async_trait]
pub trait IdentityMappingStore: Send + Sync + 'static {
async fn get_identity_mapping(
&self,
backend: &str,
identity_id: &str,
) -> Result<Option<IdentityMapping>, AuthError>;
}
#[derive(Debug, Clone)]
pub struct KratosSessionClient {
client: reqwest::Client,
public_url: String,
}
impl KratosSessionClient {
pub fn new(public_url: impl Into<String>) -> Self {
Self {
client: reqwest::Client::new(),
public_url: public_url.into(),
}
}
}
#[async_trait]
impl SessionClient for KratosSessionClient {
async fn to_session(
&self,
cookie: Option<&str>,
token: Option<&str>,
) -> Result<Value, AuthError> {
let url = format!("{}/sessions/whoami", self.public_url.trim_end_matches('/'));
let mut req = self.client.get(&url).header("accept", "application/json");
if let Some(token) = token {
req = req.header("X-Session-Token", token);
}
if let Some(cookie) = cookie {
req = req.header("Cookie", cookie);
}
let response = req
.send()
.await
.map_err(|e| AuthError::InvalidSession(e.to_string()))?;
if response.status().is_success() {
response
.json()
.await
.map_err(|e| AuthError::InvalidSession(e.to_string()))
} else {
Err(AuthError::InvalidSession(format!(
"session validation returned {}",
response.status()
)))
}
}
}