use serde::{Deserialize, Serialize};
use crate::client::CallbackParams;
use crate::error::IntegrationError;
use crate::session::OAuthSession;
#[cfg(feature = "axum")]
pub mod axum;
#[cfg(feature = "actix")]
pub mod actix;
#[cfg(feature = "tower")]
pub mod tower;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct OAuthCallbackQuery {
pub code: Option<String>,
pub state: Option<String>,
pub iss: Option<String>,
pub error: Option<String>,
pub error_description: Option<String>,
}
impl OAuthCallbackQuery {
#[must_use]
pub fn new(code: impl Into<String>, state: impl Into<String>) -> Self {
Self {
code: Some(code.into()),
state: Some(state.into()),
iss: None,
error: None,
error_description: None,
}
}
#[must_use]
pub fn new_error(error: impl Into<String>, description: Option<String>) -> Self {
Self {
code: None,
state: None,
iss: None,
error: Some(error.into()),
error_description: description,
}
}
#[must_use]
pub fn with_iss(mut self, iss: impl Into<String>) -> Self {
self.iss = Some(iss.into());
self
}
pub fn to_callback_params(&self) -> Result<CallbackParams, IntegrationError> {
if let Some(err) = &self.error {
return Err(IntegrationError::OAuthError {
error: err.clone(),
description: self.error_description.clone().unwrap_or_default(),
});
}
let code = self
.code
.as_ref()
.ok_or(IntegrationError::MissingCode)?
.clone();
let state = self
.state
.as_ref()
.ok_or(IntegrationError::MissingState)?
.clone();
let mut params = CallbackParams::new(code, state);
if let Some(iss) = &self.iss {
params = params.with_iss(iss.clone());
}
Ok(params)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuthenticatedUser {
pub did: String,
pub access_token: String,
pub dpop_thumbprint: String,
pub scope: Option<String>,
}
impl AuthenticatedUser {
#[must_use]
pub fn new(
did: impl Into<String>,
access_token: impl Into<String>,
dpop_thumbprint: impl Into<String>,
) -> Self {
Self {
did: did.into(),
access_token: access_token.into(),
dpop_thumbprint: dpop_thumbprint.into(),
scope: None,
}
}
#[must_use]
pub fn with_scope(mut self, scope: impl Into<String>) -> Self {
self.scope = Some(scope.into());
self
}
#[must_use]
pub fn did(&self) -> &str {
&self.did
}
#[must_use]
pub fn access_token(&self) -> &str {
&self.access_token
}
#[must_use]
pub fn dpop_thumbprint(&self) -> &str {
&self.dpop_thumbprint
}
#[must_use]
pub fn scope(&self) -> Option<&str> {
self.scope.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct OAuthSessionExtension {
pub user: AuthenticatedUser,
pub session: Option<OAuthSession>,
}
impl OAuthSessionExtension {
#[must_use]
pub fn new(user: AuthenticatedUser) -> Self {
Self {
user,
session: None,
}
}
#[must_use]
pub fn from_session(session: OAuthSession) -> Self {
let user = AuthenticatedUser {
did: session.sub.clone(),
access_token: session.access_token.clone(),
dpop_thumbprint: session.dpop_key.jwk_thumbprint(),
scope: session.scope.clone(),
};
Self {
user,
session: Some(session),
}
}
}