oauth2_client/jwt_authorization_grant/
flow.rs

1use http_api_client::{Client, ClientRespondEndpointError};
2use oauth2_core::{
3    jwt_authorization_grant::access_token_response::{
4        ErrorBody as AT_RES_ErrorBody, SuccessfulBody as AT_RES_SuccessfulBody,
5    },
6    serde::{de::DeserializeOwned, Serialize},
7    types::Scope,
8};
9
10use crate::ProviderExtJwtAuthorizationGrant;
11
12use super::{AccessTokenEndpoint, AccessTokenEndpointError};
13
14//
15//
16//
17#[derive(Debug, Clone)]
18pub struct Flow<C>
19where
20    C: Client,
21{
22    pub client_with_token: C,
23}
24impl<C> Flow<C>
25where
26    C: Client,
27{
28    pub fn new(client_with_token: C) -> Self {
29        Self { client_with_token }
30    }
31}
32
33impl<C> Flow<C>
34where
35    C: Client + Send + Sync,
36{
37    pub async fn execute<SCOPE>(
38        &self,
39        provider: &(dyn ProviderExtJwtAuthorizationGrant<Scope = SCOPE> + Send + Sync),
40        scopes: impl Into<Option<Vec<SCOPE>>>,
41    ) -> Result<AT_RES_SuccessfulBody<SCOPE>, FlowExecuteError>
42    where
43        SCOPE: Scope + Serialize + DeserializeOwned + Send + Sync,
44    {
45        // Step 1
46        let scopes = scopes.into().or_else(|| provider.scopes_default());
47
48        let access_token_endpoint = AccessTokenEndpoint::new(provider, scopes);
49
50        let access_token_ret = self
51            .client_with_token
52            .respond_endpoint(&access_token_endpoint)
53            .await
54            .map_err(|err| match err {
55                ClientRespondEndpointError::RespondFailed(err) => {
56                    FlowExecuteError::AccessTokenEndpointRespondFailed(Box::new(err))
57                }
58                ClientRespondEndpointError::EndpointRenderRequestFailed(err) => {
59                    FlowExecuteError::AccessTokenEndpointError(err)
60                }
61                ClientRespondEndpointError::EndpointParseResponseFailed(err) => {
62                    FlowExecuteError::AccessTokenEndpointError(err)
63                }
64            })?;
65
66        let access_token_successful_body =
67            access_token_ret.map_err(FlowExecuteError::AccessTokenFailed)?;
68
69        Ok(access_token_successful_body)
70    }
71}
72
73#[derive(thiserror::Error, Debug)]
74pub enum FlowExecuteError {
75    #[error("AccessTokenEndpointRespondFailed {0}")]
76    AccessTokenEndpointRespondFailed(Box<dyn std::error::Error + Send + Sync>),
77    #[error("AccessTokenEndpointError {0}")]
78    AccessTokenEndpointError(AccessTokenEndpointError),
79    #[error("AccessTokenFailed {0:?}")]
80    AccessTokenFailed(AT_RES_ErrorBody),
81}