alibi_plugins/oauth_provider/
extension_authentication.rs1use super::{OAuthProviderConfig, OAuthProviderPlugin};
2use alibi_core::CallbackContext;
3use alibi_core::endpoint::EndpointError;
4use async_trait::async_trait;
5use serde_json::Value;
6use std::sync::Arc;
7
8#[derive(Debug, Clone)]
9pub struct OAuthExtensionClientAuthentication {
10 pub assertion_types: Option<Vec<String>>,
11 pub strategy: Arc<dyn OAuthClientAuthenticationStrategy>,
12}
13
14pub struct OAuthClientAssertionInput<'a> {
15 pub context: CallbackContext,
16 pub options: &'a OAuthProviderConfig,
17 pub assertion: &'a str,
18 pub assertion_type: &'a str,
19 pub client_id: Option<&'a str>,
20 pub expected_audience: &'a str,
21}
22
23#[derive(Debug, Clone)]
24pub struct OAuthVerifiedClientAssertion {
25 pub client_id: String,
26 pub confirmation: Option<Value>,
27}
28
29#[async_trait]
30pub trait OAuthClientAuthenticationStrategy: Send + Sync + std::fmt::Debug {
31 async fn authenticate(
32 &self,
33 input: OAuthClientAssertionInput<'_>,
34 ) -> Result<OAuthVerifiedClientAssertion, EndpointError>;
35}
36
37impl OAuthProviderPlugin {
38 pub(super) fn supported_auth_methods(&self, include_none: bool) -> Vec<String> {
39 super::unique(
40 include_none
41 .then_some("none")
42 .into_iter()
43 .chain([
44 "client_secret_basic",
45 "client_secret_post",
46 "private_key_jwt",
47 ])
48 .map(str::to_owned)
49 .chain(
50 self.config
51 .extensions
52 .iter()
53 .flat_map(|extension| extension.client_authentication.keys().cloned()),
54 )
55 .collect(),
56 )
57 }
58 pub(super) fn is_extension_auth_method(&self, method: &str) -> bool {
59 self.config
60 .extensions
61 .iter()
62 .any(|extension| extension.client_authentication.contains_key(method))
63 }
64 pub(super) fn client_authentication_strategy(
65 &self,
66 assertion_type: &str,
67 ) -> Option<(&str, &OAuthExtensionClientAuthentication)> {
68 if assertion_type == "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" {
69 return None;
70 }
71 self.config
72 .extensions
73 .iter()
74 .flat_map(|extension| &extension.client_authentication)
75 .find(|(method, strategy)| {
76 strategy.assertion_types.as_ref().map_or_else(
77 || method.as_str() == assertion_type,
78 |types| types.iter().any(|value| value == assertion_type),
79 )
80 })
81 .map(|(method, strategy)| (method.as_str(), strategy))
82 }
83}