-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Smithy Bearer Auth #3102
Smithy Bearer Auth #3102
Changes from 11 commits
ca45abd
932b302
0ccab92
b90893b
d8e58ed
ca282bb
f6111ca
0f4113b
1f9316f
078e450
f0741cc
341d524
a077743
d3fbad8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/** | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0. | ||
*/ | ||
#pragma once | ||
|
||
#include <smithy/identity/auth/AuthScheme.h> | ||
#include <smithy/identity/auth/built-in/BearerTokenAuthSchemeOption.h> | ||
#include <smithy/identity/identity/AwsBearerTokenIdentityBase.h> | ||
#include <smithy/identity/resolver/AwsBearerTokenIdentityResolver.h> | ||
#include <smithy/identity/signer/built-in/BearerTokenSigner.h> | ||
|
||
namespace smithy | ||
{ | ||
constexpr char BEARER_SIGNER[] = "Bearer"; | ||
|
||
class BearerTokenAuthScheme : public AuthScheme<AwsBearerTokenIdentityBase> | ||
{ | ||
public: | ||
using AwsCredentialIdentityResolverT = IdentityResolverBase<IdentityT>; | ||
using AwsCredentialSignerT = AwsSignerBase<IdentityT>; | ||
using BearerTokenAuthSchemeParameters = DefaultAuthSchemeResolverParameters; | ||
|
||
// This allows to override the identity resolver | ||
explicit BearerTokenAuthScheme( | ||
std::shared_ptr<AwsCredentialIdentityResolverT> identityResolver, | ||
const Aws::String &serviceName, const Aws::String ®ion) | ||
: AuthScheme(BEARER_SIGNER), m_identityResolver{identityResolver}, | ||
m_signer{Aws::MakeShared<smithy::BearerTokenSigner>( | ||
"BearerTokenAuthScheme", serviceName, region)} | ||
{ | ||
assert(m_identityResolver); | ||
assert(m_signer); | ||
} | ||
|
||
explicit BearerTokenAuthScheme(const Aws::String &serviceName, | ||
const Aws::String ®ion) | ||
: BearerTokenAuthScheme( | ||
Aws::MakeShared<DefaultAwsBearerTokenIdentityResolver>( | ||
"BearerTokenAuthScheme"), | ||
serviceName, region) | ||
{ | ||
assert(m_identityResolver); | ||
|
||
assert(m_signer); | ||
} | ||
|
||
virtual ~BearerTokenAuthScheme() = default; | ||
|
||
std::shared_ptr<AwsCredentialIdentityResolverT> identityResolver() override | ||
{ | ||
return m_identityResolver; | ||
} | ||
|
||
std::shared_ptr<AwsCredentialSignerT> signer() override { return m_signer; } | ||
|
||
protected: | ||
std::shared_ptr<AwsCredentialIdentityResolverT> m_identityResolver; | ||
std::shared_ptr<AwsCredentialSignerT> m_signer; | ||
}; | ||
} // namespace smithy |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,18 @@ | ||||||
/** | ||||||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||||||
* SPDX-License-Identifier: Apache-2.0. | ||||||
*/ | ||||||
#pragma once | ||||||
|
||||||
#include <smithy/identity/auth/AuthSchemeOption.h> | ||||||
|
||||||
namespace smithy | ||||||
{ | ||||||
struct BearerTokenAuthSchemeOption | ||||||
{ | ||||||
static AuthSchemeOption bearerTokenAuthSchemeOption; | ||||||
}; | ||||||
|
||||||
AuthSchemeOption BearerTokenAuthSchemeOption::bearerTokenAuthSchemeOption = | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can change that but the main reason for having the variable is usage from other places, so that way we just refer to one constant instead of copies elsewhere. I think we should extend this to the other auths too if you like that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can refer to it other places using |
||||||
AuthSchemeOption("Bearer"); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where did you get this string btw? in the smithy docs its There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Line 587 in af8d1fb
this is the signer we use.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we moving to a new signer name? Coz, that's not what legacy signer name is . If so, an easy change. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do you think that is the name of the signer? look at what exists for the SigV4AuthSchemeOption and SigV4aAuthSchemeOption this is the AuthScheme name, which as in the SRA reference is named as |
||||||
} // namespace smithy |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/** | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0. | ||
*/ | ||
#pragma once | ||
|
||
#include <smithy/identity/auth/AuthSchemeResolverBase.h> | ||
#include <smithy/identity/auth/built-in/BearerTokenAuthSchemeOption.h> | ||
|
||
namespace smithy | ||
{ | ||
template <typename ServiceAuthSchemeParametersT = | ||
DefaultAuthSchemeResolverParameters> | ||
class BearerTokenAuthSchemeResolver | ||
: public AuthSchemeResolverBase<ServiceAuthSchemeParametersT> | ||
{ | ||
public: | ||
using ServiceAuthSchemeParameters = ServiceAuthSchemeParametersT; | ||
virtual ~BearerTokenAuthSchemeResolver() = default; | ||
|
||
Aws::Vector<AuthSchemeOption> resolveAuthScheme( | ||
const ServiceAuthSchemeParameters &identityProperties) override | ||
{ | ||
AWS_UNREFERENCED_PARAM(identityProperties); | ||
return {BearerTokenAuthSchemeOption::bearerTokenAuthSchemeOption}; | ||
} | ||
}; | ||
} // namespace smithy |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,16 +4,92 @@ | |
*/ | ||
#pragma once | ||
|
||
#include <aws/core/auth/bearer-token-provider/AWSBearerTokenProviderBase.h> | ||
#include <aws/core/auth/bearer-token-provider/SSOBearerTokenProvider.h> | ||
#include <smithy/identity/identity/AwsBearerTokenIdentity.h> | ||
#include <smithy/identity/resolver/AwsIdentityResolverBase.h> | ||
|
||
#include <smithy/identity/identity/AwsBearerTokenIdentity.h> | ||
namespace smithy | ||
{ | ||
|
||
static const char SSO_DEFAULT_BEARER_TOKEN_PROVIDER_CHAIN_LOG_TAG[] = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same comment as above, maybe we should just inline these to avoid pollution There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can put it in the class scope to make it better |
||
"SSOBearerTokenProvider"; | ||
static const char BEARER_TOKEN_PROVIDER_CHAIN_LOG_TAG[] = "BearerTokenProvider"; | ||
|
||
class AwsBearerTokenIdentityResolver | ||
: public IdentityResolverBase<AwsBearerTokenIdentityBase> | ||
{ | ||
public: | ||
using IdentityT = AwsBearerTokenIdentity; | ||
virtual ~AwsBearerTokenIdentityResolver() = default; | ||
|
||
AwsBearerTokenIdentityResolver() = default; | ||
|
||
AwsBearerTokenIdentityResolver( | ||
const Aws::Vector< | ||
std::shared_ptr<Aws::Auth::AWSBearerTokenProviderBase>> | ||
&providerChain) | ||
: m_providerChainLegacy{providerChain} | ||
{ | ||
} | ||
|
||
ResolveIdentityFutureOutcome | ||
getIdentity(const IdentityProperties &identityProperties, | ||
const AdditionalParameters &additionalParameters) override | ||
{ | ||
AWS_UNREFERENCED_PARAM(identityProperties); | ||
AWS_UNREFERENCED_PARAM(additionalParameters); | ||
for (auto &bearerTokenProvider : m_providerChainLegacy) | ||
{ | ||
if (!bearerTokenProvider) | ||
{ | ||
AWS_LOGSTREAM_FATAL( | ||
BEARER_TOKEN_PROVIDER_CHAIN_LOG_TAG, | ||
"Unexpected nullptr in " | ||
"DefaultBearerTokenProviderChain::m_providerChain"); | ||
return Aws::Client::AWSError<Aws::Client::CoreErrors>( | ||
Aws::Client::CoreErrors::INVALID_PARAMETER_VALUE, "", | ||
"Unexpected nullptr in " | ||
"BearerTokenProviderChain::m_providerChain", | ||
false); | ||
} | ||
auto bearerToken = bearerTokenProvider->GetAWSBearerToken(); | ||
if (!bearerToken.IsExpiredOrEmpty()) | ||
{ | ||
auto outcomePtr = Aws::MakeUnique<AwsBearerTokenIdentity>( | ||
BEARER_TOKEN_PROVIDER_CHAIN_LOG_TAG); | ||
outcomePtr->token() = bearerToken.GetToken(); | ||
outcomePtr->expiration() = bearerToken.GetExpiration(); | ||
return ResolveIdentityFutureOutcome(std::move(outcomePtr)); | ||
} | ||
} | ||
|
||
return Aws::Client::AWSError<Aws::Client::CoreErrors>( | ||
Aws::Client::CoreErrors::NOT_INITIALIZED, "", | ||
"No bearer token provider in chain found", false); | ||
} | ||
|
||
void AddBearerTokenProvider( | ||
std::shared_ptr<Aws::Auth::AWSBearerTokenProviderBase> provider) | ||
{ | ||
m_providerChainLegacy.emplace_back(std::move(provider)); | ||
} | ||
|
||
protected: | ||
Aws::Vector<std::shared_ptr<Aws::Auth::AWSBearerTokenProviderBase>> | ||
m_providerChainLegacy; | ||
}; | ||
|
||
namespace smithy { | ||
class AwsBearerTokenIdentityResolver : public IdentityResolverBase<AwsBearerTokenIdentity> { | ||
public: | ||
using IdentityT = AwsBearerTokenIdentity; | ||
virtual ~AwsBearerTokenIdentityResolver() = default; | ||
class DefaultAwsBearerTokenIdentityResolver | ||
: public AwsBearerTokenIdentityResolver | ||
{ | ||
public: | ||
using IdentityT = AwsBearerTokenIdentity; | ||
virtual ~DefaultAwsBearerTokenIdentityResolver() = default; | ||
|
||
ResolveIdentityFutureOutcome getIdentity(const IdentityProperties& identityProperties, const AdditionalParameters& additionalParameters) override = 0; | ||
}; | ||
} | ||
DefaultAwsBearerTokenIdentityResolver() | ||
: AwsBearerTokenIdentityResolver( | ||
{Aws::MakeShared<Aws::Auth::SSOBearerTokenProvider>( | ||
SSO_DEFAULT_BEARER_TOKEN_PROVIDER_CHAIN_LOG_TAG)}){}; | ||
}; | ||
} // namespace smithy |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/** | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <smithy/identity/identity/AwsBearerTokenIdentityBase.h> | ||
#include <smithy/identity/signer/AwsSignerBase.h> | ||
|
||
#include <aws/core/auth/signer/AWSAuthSignerHelper.h> | ||
#include <aws/core/http/HttpRequest.h> | ||
#include <aws/crt/http/HttpConnection.h> | ||
#include <aws/crt/http/HttpRequestResponse.h> | ||
|
||
namespace smithy | ||
{ | ||
static const char AUTHORIZATION_HEADER[] = "authorization"; | ||
|
||
class BearerTokenSigner : public AwsSignerBase<AwsBearerTokenIdentityBase> | ||
{ | ||
|
||
public: | ||
static const char LOGGING_TAG[]; | ||
|
||
using BearerTokenAuthSchemeParameters = | ||
smithy::DefaultAuthSchemeResolverParameters; | ||
explicit BearerTokenSigner(const Aws::String &serviceName, | ||
const Aws::String ®ion) | ||
: m_serviceName(serviceName), m_region(region) | ||
{ | ||
} | ||
|
||
SigningFutureOutcome | ||
sign(std::shared_ptr<HttpRequest> httpRequest, | ||
const smithy::AwsBearerTokenIdentityBase &identity, | ||
SigningProperties properties) override | ||
{ | ||
AWS_UNREFERENCED_PARAM(properties); | ||
|
||
if (Aws::Http::Scheme::HTTPS != httpRequest->GetUri().GetScheme()) | ||
{ | ||
// Clients MUST always use TLS (https) or equivalent transport | ||
// security when making requests with bearer tokens. | ||
// https://datatracker.ietf.org/doc/html/rfc6750 | ||
AWS_LOGSTREAM_ERROR( | ||
LOGGING_TAG, | ||
"HTTPS scheme must be used with a bearer token authorization"); | ||
return SigningError( | ||
Aws::Client::CoreErrors::INVALID_PARAMETER_VALUE, "", | ||
"Failed to sign the request with bearer", false); | ||
} | ||
|
||
httpRequest->SetHeaderValue(AUTHORIZATION_HEADER, | ||
"Bearer " + identity.token()); | ||
|
||
return SigningFutureOutcome(std::move(httpRequest)); | ||
} | ||
|
||
virtual ~BearerTokenSigner(){}; | ||
|
||
protected: | ||
Aws::String m_serviceName; | ||
Aws::String m_region; | ||
}; | ||
|
||
const char BearerTokenSigner::LOGGING_TAG[] = "BearerTokenSigner"; | ||
} // namespace smithy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was thinking about this the other day, do we really need this in its own constant or can we just pass the string in the parent ctor i.e.
we avoid some namespace pollution that way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had raised this before (during autha) but we agreed putting this in namespace smithy to comply with what Sergey originally proposed. We do pass it in the base class constructor. I can simply pass the raw string .
Whatever you finalize. I am ok with either
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
raw string is better in my opinion thinking about it, one less thing in the namespace that is actually internal to us