aws_credential_types/provider/
token.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! AWS Access Tokens for SSO
7//!
8//! When authenticating with an AWS Builder ID, single sign-on (SSO) will provide
9//! an access token that can then be used to authenticate with services such as
10//! Code Catalyst.
11//!
12//! This module provides the [`ProvideToken`] trait that is used to configure
13//! token providers in the SDK config.
14
15use crate::{provider::error::TokenError, provider::future, Token};
16use aws_smithy_runtime_api::client::{
17    identity::{IdentityCachePartition, IdentityFuture, ResolveIdentity},
18    runtime_components::RuntimeComponents,
19};
20use aws_smithy_runtime_api::impl_shared_conversions;
21use aws_smithy_types::config_bag::ConfigBag;
22use std::sync::Arc;
23
24/// Result type for token providers
25pub type Result = std::result::Result<Token, TokenError>;
26
27/// Access Token Provider
28pub trait ProvideToken: Send + Sync + std::fmt::Debug {
29    /// Returns a future that provides an access token.
30    fn provide_token<'a>(&'a self) -> future::ProvideToken<'a>
31    where
32        Self: 'a;
33}
34
35impl ProvideToken for Token {
36    fn provide_token<'a>(&'a self) -> future::ProvideToken<'a>
37    where
38        Self: 'a,
39    {
40        future::ProvideToken::ready(Ok(self.clone()))
41    }
42}
43
44/// Access token provider wrapper that may be shared.
45///
46/// Newtype wrapper around [`ProvideToken`] that implements `Clone` using an internal `Arc`.
47#[derive(Clone, Debug)]
48pub struct SharedTokenProvider(Arc<dyn ProvideToken>, IdentityCachePartition);
49
50impl SharedTokenProvider {
51    /// Create a new [`SharedTokenProvider`] from [`ProvideToken`].
52    ///
53    /// The given provider will be wrapped in an internal `Arc`. If your
54    /// provider is already in an `Arc`, use `SharedTokenProvider::from(provider)` instead.
55    pub fn new(provider: impl ProvideToken + 'static) -> Self {
56        Self(Arc::new(provider), IdentityCachePartition::new())
57    }
58}
59
60impl AsRef<dyn ProvideToken> for SharedTokenProvider {
61    fn as_ref(&self) -> &(dyn ProvideToken + 'static) {
62        self.0.as_ref()
63    }
64}
65
66impl From<Arc<dyn ProvideToken>> for SharedTokenProvider {
67    fn from(provider: Arc<dyn ProvideToken>) -> Self {
68        SharedTokenProvider(provider, IdentityCachePartition::new())
69    }
70}
71
72impl ProvideToken for SharedTokenProvider {
73    fn provide_token<'a>(&'a self) -> future::ProvideToken<'a>
74    where
75        Self: 'a,
76    {
77        self.0.provide_token()
78    }
79}
80
81impl ResolveIdentity for SharedTokenProvider {
82    fn resolve_identity<'a>(
83        &'a self,
84        _runtime_components: &'a RuntimeComponents,
85        _config_bag: &'a ConfigBag,
86    ) -> IdentityFuture<'a> {
87        IdentityFuture::new(async move { Ok(self.provide_token().await?.into()) })
88    }
89
90    fn cache_partition(&self) -> Option<IdentityCachePartition> {
91        Some(self.1)
92    }
93}
94
95impl_shared_conversions!(convert SharedTokenProvider from ProvideToken using SharedTokenProvider::new);
96
97#[cfg(test)]
98mod tests {
99    use aws_smithy_runtime_api::client::identity::SharedIdentityResolver;
100
101    use super::*;
102
103    #[test]
104    fn reuses_cache_partition() {
105        let token = Token::new("token", None);
106        let provider = SharedTokenProvider::new(token);
107        let partition = provider.cache_partition();
108        assert!(partition.is_some());
109
110        let identity_resolver = SharedIdentityResolver::new(provider);
111        let identity_partition = identity_resolver.cache_partition();
112
113        assert!(partition.unwrap() == identity_partition);
114    }
115}