in src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp [80:182]
bool AWSAuthV4Signer::SignRequestWithSigV4a(Aws::Http::HttpRequest& request, const char* region, const char* serviceName,
bool signBody, long long expirationTimeInSeconds, Aws::Crt::Auth::SignatureType signatureType) const
{
AWSCredentials credentials = GetCredentials(request.GetServiceSpecificParameters());
auto crtCredentials = Aws::MakeShared<Aws::Crt::Auth::Credentials>(v4AsymmetricLogTag,
Aws::Crt::ByteCursorFromCString(credentials.GetAWSAccessKeyId().c_str()),
Aws::Crt::ByteCursorFromCString(credentials.GetAWSSecretKey().c_str()),
Aws::Crt::ByteCursorFromCString(credentials.GetSessionToken().c_str()),
credentials.GetExpiration().Seconds());
Aws::Crt::Auth::AwsSigningConfig awsSigningConfig;
awsSigningConfig.SetSigningAlgorithm(static_cast<Aws::Crt::Auth::SigningAlgorithm>(AWSSigningAlgorithm::ASYMMETRIC_SIGV4));
awsSigningConfig.SetSignatureType(signatureType);
awsSigningConfig.SetRegion(region);
awsSigningConfig.SetService(serviceName);
awsSigningConfig.SetSigningTimepoint(GetSigningTimestamp().UnderlyingTimestamp());
awsSigningConfig.SetUseDoubleUriEncode(m_urlEscapePath);
awsSigningConfig.SetShouldNormalizeUriPath(true);
awsSigningConfig.SetOmitSessionToken(false);
awsSigningConfig.SetShouldSignHeaderUserData(reinterpret_cast<void*>(const_cast<Aws::Set<Aws::String>*>(&m_unsignedHeaders)));
awsSigningConfig.SetShouldSignHeaderCallback([](const Aws::Crt::ByteCursor *name, void *user_data) {
Aws::Set<Aws::String>* unsignedHeaders = static_cast<Aws::Set<Aws::String>*>(user_data);
Aws::String headerKey(reinterpret_cast<const char*>(name->ptr), name->len);
return unsignedHeaders->find(Aws::Utils::StringUtils::ToLower(headerKey.c_str())) == unsignedHeaders->cend();
});
if (signatureType == Aws::Crt::Auth::SignatureType::HttpRequestViaHeaders)
{
Aws::String payloadHash(UNSIGNED_PAYLOAD);
if(signBody || request.GetUri().GetScheme() != Http::Scheme::HTTPS)
{
if (!request.GetContentBody())
{
AWS_LOGSTREAM_DEBUG(v4AsymmetricLogTag, "Using cached empty string sha256 " << EMPTY_STRING_SHA256 << " because payload is empty.");
payloadHash = EMPTY_STRING_SHA256;
}
else
{
// The hash will be calculated from the payload during signing.
payloadHash = {};
}
}
else
{
AWS_LOGSTREAM_DEBUG(v4AsymmetricLogTag, "Note: Http payloads are not being signed. signPayloads=" << signBody
<< " http scheme=" << Http::SchemeMapper::ToString(request.GetUri().GetScheme()));
}
awsSigningConfig.SetSignedBodyValue(payloadHash.c_str());
awsSigningConfig.SetSignedBodyHeader(m_includeSha256HashHeader ? Aws::Crt::Auth::SignedBodyHeaderType::XAmzContentSha256 : Aws::Crt::Auth::SignedBodyHeaderType::None);
}
else if (signatureType == Aws::Crt::Auth::SignatureType::HttpRequestViaQueryParams)
{
if (ServiceRequireUnsignedPayload(serviceName))
{
awsSigningConfig.SetSignedBodyValue(UNSIGNED_PAYLOAD);
}
else
{
awsSigningConfig.SetSignedBodyValue(EMPTY_STRING_SHA256);
}
}
else
{
AWS_LOGSTREAM_ERROR(v4AsymmetricLogTag, "The signature type should be either \"HttpRequestViaHeaders\" or \"HttpRequestViaQueryParams\"");
return false;
}
awsSigningConfig.SetExpirationInSeconds(static_cast<uint64_t>(expirationTimeInSeconds));
awsSigningConfig.SetCredentials(crtCredentials);
std::shared_ptr<Aws::Crt::Http::HttpRequest> crtHttpRequest = request.ToCrtHttpRequest();
bool success = true;
m_crtSigner.SignRequest(crtHttpRequest, awsSigningConfig,
[&request, &success, signatureType](const std::shared_ptr<Aws::Crt::Http::HttpRequest>& signedCrtHttpRequest, int errorCode) {
success = (errorCode == AWS_ERROR_SUCCESS);
if (success)
{
if (signatureType == Aws::Crt::Auth::SignatureType::HttpRequestViaHeaders)
{
for (size_t i = 0; i < signedCrtHttpRequest->GetHeaderCount(); i++)
{
Aws::Crt::Optional<Aws::Crt::Http::HttpHeader> httpHeader = signedCrtHttpRequest->GetHeader(i);
request.SetHeaderValue(Aws::String(reinterpret_cast<const char*>(httpHeader->name.ptr), httpHeader->name.len),
Aws::String(reinterpret_cast<const char*>(httpHeader->value.ptr), httpHeader->value.len));
}
}
else if (signatureType == Aws::Crt::Auth::SignatureType::HttpRequestViaQueryParams)
{
Aws::Http::URI newPath(reinterpret_cast<const char*>(signedCrtHttpRequest->GetPath()->ptr));
request.GetUri().SetQueryString(newPath.GetQueryString());
}
else
{
AWS_LOGSTREAM_ERROR(v4AsymmetricLogTag, "No action to take when signature type is neither \"HttpRequestViaHeaders\" nor \"HttpRequestViaQueryParams\"");
success = false;
}
}
else
{
AWS_LOGSTREAM_ERROR(v4AsymmetricLogTag, "Encountered internal error during signing process with AWS signature version 4 (Asymmetric):" << aws_error_str(errorCode));
}
}
);
return success;
}