authkestra_engine/flow/
mod.rs1#![warn(missing_docs)]
15
16use crate::auth::{error::AuthError, state::Identity, CredentialsProvider, UserMapper};
17pub use crate::auth::{ErasedOAuthFlow, Session, SessionConfig, SessionStore};
18use async_trait::async_trait;
19use serde::{Deserialize, Serialize};
20
21pub use chrono;
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
25#[non_exhaustive]
26pub struct FlowContext {
27 pub state: String,
29 pub params: HashMap<String, String>,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
35pub enum FlowResult {
36 Complete(Identity),
38 Redirect(String),
40 Pending,
42}
43
44#[async_trait]
46pub trait Flow: Send + Sync {
47 fn id(&self) -> &str;
49
50 async fn execute(&self, ctx: FlowContext) -> Result<FlowResult, AuthError>;
52}
53
54use std::collections::HashMap;
55
56pub use crate::engine::{Configured, Engine, EngineBuilder, Missing};
57
58pub mod client_credentials_flow;
60pub mod device_flow;
62pub mod oauth2;
64
65pub use client_credentials_flow::ClientCredentialsFlow;
66pub use device_flow::{DeviceAuthorizationResponse, DeviceFlow};
67pub use oauth2::OAuth2Flow;
68
69#[non_exhaustive]
71pub struct CredentialsFlow<P: CredentialsProvider, M: UserMapper = ()> {
72 provider: P,
73 mapper: Option<M>,
74}
75
76impl<P: CredentialsProvider> CredentialsFlow<P, ()> {
77 pub fn new(provider: P) -> Self {
79 Self {
80 provider,
81 mapper: None,
82 }
83 }
84}
85
86impl<P: CredentialsProvider, M: UserMapper> CredentialsFlow<P, M> {
87 pub fn with_mapper(provider: P, mapper: M) -> Self {
89 Self {
90 provider,
91 mapper: Some(mapper),
92 }
93 }
94
95 pub async fn authenticate(
97 &self,
98 creds: P::Credentials,
99 ) -> Result<(Identity, Option<M::LocalUser>), AuthError> {
100 let identity = self.provider.authenticate(creds).await?;
101
102 let local_user = if let Some(mapper) = &self.mapper {
103 Some(mapper.map_user(&identity).await?)
104 } else {
105 None
106 };
107
108 Ok((identity, local_user))
109 }
110}