Skip to content

Commit 5913125

Browse files
authored
Smithy Bearer Auth (#3102)
* bearer token placeholder * test placeholder * more placeholder changes * fixes * fixes wip * fixes * make tests functional * make test provider the first in chain for test * cleanup * run clang formatter llvm * remove redundant headers * fix scheme id name * fixes * address comments
1 parent c5c1967 commit 5913125

File tree

9 files changed

+371
-23
lines changed

9 files changed

+371
-23
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
#pragma once
6+
7+
#include <smithy/identity/auth/AuthScheme.h>
8+
#include <smithy/identity/auth/built-in/BearerTokenAuthSchemeOption.h>
9+
#include <smithy/identity/identity/AwsBearerTokenIdentityBase.h>
10+
#include <smithy/identity/resolver/AwsBearerTokenIdentityResolver.h>
11+
#include <smithy/identity/signer/built-in/BearerTokenSigner.h>
12+
namespace smithy
13+
{
14+
class BearerTokenAuthScheme : public AuthScheme<AwsBearerTokenIdentityBase>
15+
{
16+
public:
17+
using AwsCredentialIdentityResolverT = IdentityResolverBase<IdentityT>;
18+
using AwsCredentialSignerT = AwsSignerBase<IdentityT>;
19+
using BearerTokenAuthSchemeParameters = DefaultAuthSchemeResolverParameters;
20+
21+
// This allows to override the identity resolver
22+
explicit BearerTokenAuthScheme(
23+
std::shared_ptr<AwsCredentialIdentityResolverT> identityResolver,
24+
const Aws::String &serviceName, const Aws::String &region)
25+
: AuthScheme("smithy.api#HTTPBearerAuth"),
26+
m_identityResolver{identityResolver},
27+
m_signer{Aws::MakeShared<smithy::BearerTokenSigner>(
28+
"BearerTokenAuthScheme", serviceName, region)}
29+
{
30+
assert(m_identityResolver);
31+
assert(m_signer);
32+
}
33+
34+
explicit BearerTokenAuthScheme(const Aws::String &serviceName,
35+
const Aws::String &region)
36+
: BearerTokenAuthScheme(
37+
Aws::MakeShared<DefaultAwsBearerTokenIdentityResolver>(
38+
"BearerTokenAuthScheme"),
39+
serviceName, region)
40+
{
41+
assert(m_identityResolver);
42+
43+
assert(m_signer);
44+
}
45+
46+
virtual ~BearerTokenAuthScheme() = default;
47+
48+
std::shared_ptr<AwsCredentialIdentityResolverT> identityResolver() override
49+
{
50+
return m_identityResolver;
51+
}
52+
53+
std::shared_ptr<AwsCredentialSignerT> signer() override { return m_signer; }
54+
55+
protected:
56+
std::shared_ptr<AwsCredentialIdentityResolverT> m_identityResolver;
57+
std::shared_ptr<AwsCredentialSignerT> m_signer;
58+
};
59+
} // namespace smithy
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
#pragma once
6+
7+
#include <smithy/identity/auth/AuthSchemeOption.h>
8+
namespace smithy
9+
{
10+
struct BearerTokenAuthSchemeOption
11+
{
12+
static AuthSchemeOption bearerTokenAuthSchemeOption;
13+
};
14+
15+
AuthSchemeOption BearerTokenAuthSchemeOption::bearerTokenAuthSchemeOption =
16+
AuthSchemeOption("smithy.api#HTTPBearerAuth");
17+
} // namespace smithy
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
#pragma once
6+
7+
#include <smithy/identity/auth/AuthSchemeResolverBase.h>
8+
#include <smithy/identity/auth/built-in/BearerTokenAuthSchemeOption.h>
9+
10+
namespace smithy
11+
{
12+
template <typename ServiceAuthSchemeParametersT =
13+
DefaultAuthSchemeResolverParameters>
14+
class BearerTokenAuthSchemeResolver
15+
: public AuthSchemeResolverBase<ServiceAuthSchemeParametersT>
16+
{
17+
public:
18+
using ServiceAuthSchemeParameters = ServiceAuthSchemeParametersT;
19+
virtual ~BearerTokenAuthSchemeResolver() = default;
20+
21+
Aws::Vector<AuthSchemeOption> resolveAuthScheme(
22+
const ServiceAuthSchemeParameters &identityProperties) override
23+
{
24+
AWS_UNREFERENCED_PARAM(identityProperties);
25+
return {BearerTokenAuthSchemeOption::bearerTokenAuthSchemeOption};
26+
}
27+
};
28+
} // namespace smithy

src/aws-cpp-sdk-core/include/smithy/identity/identity/AwsBearerTokenIdentity.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,17 @@
99
namespace smithy {
1010
class AwsBearerTokenIdentity : public AwsBearerTokenIdentityBase {
1111
public:
12-
virtual Aws::String token() override;
12+
virtual const Aws::String &token() const override;
1313

14-
virtual Aws::Crt::Optional<AwsIdentity::DateTime> expiration() override;
14+
virtual Aws::Crt::Optional<AwsIdentity::DateTime>
15+
expiration() const override;
16+
17+
Aws::String &token() { return m_token; }
18+
19+
Aws::Crt::Optional<AwsIdentity::DateTime> &expiration()
20+
{
21+
return m_expiration;
22+
}
1523

1624
protected:
1725
Aws::String m_token;

src/aws-cpp-sdk-core/include/smithy/identity/identity/AwsBearerTokenIdentityBase.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
namespace smithy {
1010
class AwsBearerTokenIdentityBase : public AwsIdentity {
1111
public:
12-
virtual Aws::String token() = 0;
12+
virtual const Aws::String &token() const = 0;
1313

14-
virtual Aws::Crt::Optional<AwsIdentity::DateTime> expiration() override = 0 ;
14+
virtual Aws::Crt::Optional<AwsIdentity::DateTime>
15+
expiration() const override = 0;
1516
};
1617
}

src/aws-cpp-sdk-core/include/smithy/identity/identity/impl/AwsBearerTokenIdentityImpl.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
#include <smithy/identity/identity/AwsBearerTokenIdentity.h>
99

1010
namespace smithy {
11-
Aws::String AwsBearerTokenIdentity::token() {
12-
return m_token;
13-
}
11+
const Aws::String &AwsBearerTokenIdentity::token() const { return m_token; }
1412

15-
Aws::Crt::Optional<AwsIdentity::DateTime> AwsBearerTokenIdentity::expiration() {
16-
return m_expiration;
17-
}
13+
Aws::Crt::Optional<AwsIdentity::DateTime>
14+
AwsBearerTokenIdentity::expiration() const
15+
{
16+
return m_expiration;
17+
}
1818
}

src/aws-cpp-sdk-core/include/smithy/identity/resolver/AwsBearerTokenIdentityResolver.h

Lines changed: 87 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,94 @@
44
*/
55
#pragma once
66

7+
#include <aws/core/auth/bearer-token-provider/AWSBearerTokenProviderBase.h>
8+
#include <aws/core/auth/bearer-token-provider/SSOBearerTokenProvider.h>
9+
#include <smithy/identity/identity/AwsBearerTokenIdentity.h>
710
#include <smithy/identity/resolver/AwsIdentityResolverBase.h>
811

9-
#include <smithy/identity/identity/AwsBearerTokenIdentity.h>
12+
namespace smithy
13+
{
14+
15+
class AwsBearerTokenIdentityResolver
16+
: public IdentityResolverBase<AwsBearerTokenIdentityBase>
17+
{
18+
public:
19+
static const char BEARER_TOKEN_PROVIDER_CHAIN_LOG_TAG[];
20+
21+
using IdentityT = AwsBearerTokenIdentity;
22+
virtual ~AwsBearerTokenIdentityResolver() = default;
23+
24+
AwsBearerTokenIdentityResolver() = default;
25+
26+
AwsBearerTokenIdentityResolver(
27+
const Aws::Vector<
28+
std::shared_ptr<Aws::Auth::AWSBearerTokenProviderBase>>
29+
&providerChain)
30+
: m_providerChainLegacy{providerChain}
31+
{
32+
}
33+
34+
ResolveIdentityFutureOutcome
35+
getIdentity(const IdentityProperties &identityProperties,
36+
const AdditionalParameters &additionalParameters) override
37+
{
38+
AWS_UNREFERENCED_PARAM(identityProperties);
39+
AWS_UNREFERENCED_PARAM(additionalParameters);
40+
for (auto &bearerTokenProvider : m_providerChainLegacy)
41+
{
42+
if (!bearerTokenProvider)
43+
{
44+
AWS_LOGSTREAM_FATAL(
45+
BEARER_TOKEN_PROVIDER_CHAIN_LOG_TAG,
46+
"Unexpected nullptr in "
47+
"DefaultBearerTokenProviderChain::m_providerChain");
48+
return Aws::Client::AWSError<Aws::Client::CoreErrors>(
49+
Aws::Client::CoreErrors::INVALID_PARAMETER_VALUE, "",
50+
"Unexpected nullptr in "
51+
"BearerTokenProviderChain::m_providerChain",
52+
false);
53+
}
54+
auto bearerToken = bearerTokenProvider->GetAWSBearerToken();
55+
if (!bearerToken.IsExpiredOrEmpty())
56+
{
57+
auto outcomePtr = Aws::MakeUnique<AwsBearerTokenIdentity>(
58+
BEARER_TOKEN_PROVIDER_CHAIN_LOG_TAG);
59+
outcomePtr->token() = bearerToken.GetToken();
60+
outcomePtr->expiration() = bearerToken.GetExpiration();
61+
return ResolveIdentityFutureOutcome(std::move(outcomePtr));
62+
}
63+
}
64+
65+
return Aws::Client::AWSError<Aws::Client::CoreErrors>(
66+
Aws::Client::CoreErrors::NOT_INITIALIZED, "",
67+
"No bearer token provider in chain found", false);
68+
}
69+
70+
void AddBearerTokenProvider(
71+
std::shared_ptr<Aws::Auth::AWSBearerTokenProviderBase> provider)
72+
{
73+
m_providerChainLegacy.emplace_back(std::move(provider));
74+
}
75+
76+
protected:
77+
Aws::Vector<std::shared_ptr<Aws::Auth::AWSBearerTokenProviderBase>>
78+
m_providerChainLegacy;
79+
};
80+
81+
class DefaultAwsBearerTokenIdentityResolver
82+
: public AwsBearerTokenIdentityResolver
83+
{
84+
public:
85+
using IdentityT = AwsBearerTokenIdentity;
86+
virtual ~DefaultAwsBearerTokenIdentityResolver() = default;
1087

11-
namespace smithy {
12-
class AwsBearerTokenIdentityResolver : public IdentityResolverBase<AwsBearerTokenIdentity> {
13-
public:
14-
using IdentityT = AwsBearerTokenIdentity;
15-
virtual ~AwsBearerTokenIdentityResolver() = default;
88+
DefaultAwsBearerTokenIdentityResolver()
89+
: AwsBearerTokenIdentityResolver(
90+
{Aws::MakeShared<Aws::Auth::SSOBearerTokenProvider>(
91+
"SSOBearerTokenProvider")}){};
92+
};
93+
const char
94+
AwsBearerTokenIdentityResolver::BEARER_TOKEN_PROVIDER_CHAIN_LOG_TAG[] =
95+
"BearerTokenProvider";
1696

17-
ResolveIdentityFutureOutcome getIdentity(const IdentityProperties& identityProperties, const AdditionalParameters& additionalParameters) override = 0;
18-
};
19-
}
97+
} // namespace smithy
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
6+
#pragma once
7+
8+
#include <smithy/identity/identity/AwsBearerTokenIdentityBase.h>
9+
#include <smithy/identity/signer/AwsSignerBase.h>
10+
11+
#include <aws/core/auth/signer/AWSAuthSignerHelper.h>
12+
#include <aws/core/http/HttpRequest.h>
13+
#include <aws/crt/http/HttpConnection.h>
14+
#include <aws/crt/http/HttpRequestResponse.h>
15+
16+
namespace smithy
17+
{
18+
static const char AUTHORIZATION_HEADER[] = "authorization";
19+
20+
class BearerTokenSigner : public AwsSignerBase<AwsBearerTokenIdentityBase>
21+
{
22+
23+
public:
24+
static const char LOGGING_TAG[];
25+
26+
using BearerTokenAuthSchemeParameters =
27+
smithy::DefaultAuthSchemeResolverParameters;
28+
explicit BearerTokenSigner(const Aws::String &serviceName,
29+
const Aws::String &region)
30+
: m_serviceName(serviceName), m_region(region)
31+
{
32+
}
33+
34+
SigningFutureOutcome
35+
sign(std::shared_ptr<HttpRequest> httpRequest,
36+
const smithy::AwsBearerTokenIdentityBase &identity,
37+
SigningProperties properties) override
38+
{
39+
AWS_UNREFERENCED_PARAM(properties);
40+
41+
if (Aws::Http::Scheme::HTTPS != httpRequest->GetUri().GetScheme())
42+
{
43+
// Clients MUST always use TLS (https) or equivalent transport
44+
// security when making requests with bearer tokens.
45+
// https://datatracker.ietf.org/doc/html/rfc6750
46+
AWS_LOGSTREAM_ERROR(
47+
LOGGING_TAG,
48+
"HTTPS scheme must be used with a bearer token authorization");
49+
return SigningError(
50+
Aws::Client::CoreErrors::INVALID_PARAMETER_VALUE, "",
51+
"Failed to sign the request with bearer", false);
52+
}
53+
54+
httpRequest->SetHeaderValue(AUTHORIZATION_HEADER,
55+
"Bearer " + identity.token());
56+
57+
return SigningFutureOutcome(std::move(httpRequest));
58+
}
59+
60+
virtual ~BearerTokenSigner(){};
61+
62+
protected:
63+
Aws::String m_serviceName;
64+
Aws::String m_region;
65+
};
66+
67+
const char BearerTokenSigner::LOGGING_TAG[] = "BearerTokenSigner";
68+
} // namespace smithy

0 commit comments

Comments
 (0)