1use tonic::codegen::async_trait;
2
3use crate::error::Result;
4use crate::identity::{
5 AuthorizeRequest, AuthorizeResponse, GetGrantRequest, GetGrantResponse, IntrospectRequest,
6 IntrospectResponse, ListGrantsRequest, ListGrantsResponse, RevokeGrantRequest,
7 RevokeGrantResponse, TokenRequest, TokenResponse, UserInfoRequest, UserInfoResponse,
8};
9
10pub const CALLER_BEARER_TOKEN_METADATA_KEY: &str = "x-gestalt-caller-bearer-token";
11
12pub const GRANT_TYPE_AUTHORIZATION_CODE: &str = "authorization_code";
14pub const GRANT_TYPE_TOKEN_EXCHANGE: &str = "urn:ietf:params:oauth:grant-type:token-exchange";
16pub const SUBJECT_TOKEN_TYPE_ACCESS_TOKEN: &str = "urn:ietf:params:oauth:token-type:access_token";
18
19#[derive(Clone, Debug, Default, PartialEq, Eq)]
21pub struct IdentityCallContext {
22 pub caller_bearer_token: String,
24}
25#[async_trait]
26pub trait IdentityProvider: Send + Sync + 'static {
28 async fn configure(
30 &self,
31 _name: &str,
32 _config: serde_json::Map<String, serde_json::Value>,
33 ) -> Result<()> {
34 Ok(())
35 }
36
37 fn metadata(&self) -> Option<crate::api::RuntimeMetadata> {
39 None
40 }
41
42 fn warnings(&self) -> Vec<String> {
44 Vec::new()
45 }
46
47 async fn health_check(&self) -> Result<()> {
49 Ok(())
50 }
51
52 async fn start(&self) -> Result<()> {
54 Ok(())
55 }
56
57 async fn close(&self) -> Result<()> {
59 Ok(())
60 }
61
62 async fn authorize(&self, req: AuthorizeRequest) -> Result<AuthorizeResponse>;
64
65 async fn token(&self, req: TokenRequest) -> Result<TokenResponse>;
67
68 async fn introspect(&self, req: IntrospectRequest) -> Result<IntrospectResponse>;
70
71 async fn user_info(
73 &self,
74 call: IdentityCallContext,
75 req: UserInfoRequest,
76 ) -> Result<UserInfoResponse>;
77
78 async fn list_grants(
80 &self,
81 call: IdentityCallContext,
82 req: ListGrantsRequest,
83 ) -> Result<ListGrantsResponse>;
84
85 async fn get_grant(
87 &self,
88 call: IdentityCallContext,
89 req: GetGrantRequest,
90 ) -> Result<GetGrantResponse>;
91
92 async fn revoke_grant(
94 &self,
95 call: IdentityCallContext,
96 req: RevokeGrantRequest,
97 ) -> Result<RevokeGrantResponse>;
98}
99pub(crate) fn caller_bearer_token_from_metadata(metadata: &tonic::metadata::MetadataMap) -> String {
100 metadata
101 .get(CALLER_BEARER_TOKEN_METADATA_KEY)
102 .and_then(|value| value.to_str().ok())
103 .map(str::trim)
104 .filter(|value| !value.is_empty())
105 .map(str::to_owned)
106 .unwrap_or_default()
107}