Include error details into Identity exceptions (#5184)

Co-authored-by: Anton Kolesnyk <antkmsft@users.noreply.github.com>
This commit is contained in:
Anton Kolesnyk 2023-11-28 11:20:44 -08:00 committed by GitHub
parent 24ecd16308
commit bce301a841
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 10 deletions

View File

@ -10,6 +10,8 @@
### Other Changes
- [[#5141]](https://github.com/Azure/azure-sdk-for-cpp/issues/5141) Added error response details to the Identity exceptions thrown when the authority host returns error response.
## 1.6.0 (2023-11-10)
### Features Added

View File

@ -72,16 +72,13 @@ std::string TokenCredentialImpl::FormatScopes(
if (scopesIter != scopesEnd)
{
auto const scope = *scopesIter;
scopesStr += OptionalUrlEncode(scope, urlEncode);
}
scopesStr += OptionalUrlEncode(*scopesIter, urlEncode);
for (++scopesIter; scopesIter != scopesEnd; ++scopesIter)
{
auto const Separator = std::string(" "); // Element separator never gets URL-encoded
auto const scope = *scopesIter;
scopesStr += Separator + OptionalUrlEncode(scope, urlEncode);
constexpr auto Separator = " "; // Element separator never gets URL-encoded
for (++scopesIter; scopesIter != scopesEnd; ++scopesIter)
{
scopesStr += Separator + OptionalUrlEncode(*scopesIter, urlEncode);
}
}
}
@ -117,11 +114,16 @@ AccessToken TokenCredentialImpl::GetToken(
request = shouldRetry(statusCode, *response);
if (request == nullptr)
{
auto const bodyStream = response->ExtractBodyStream();
auto const bodyVec = bodyStream ? bodyStream->ReadToEnd(context) : response->GetBody();
auto const responseBody
= std::string(reinterpret_cast<char const*>(bodyVec.data()), bodyVec.size());
throw std::runtime_error(
std::string("error response: ")
+ std::to_string(
static_cast<std::underlying_type<decltype(statusCode)>::type>(statusCode))
+ " " + response->GetReasonPhrase());
+ " " + response->GetReasonPhrase() + "\n\n" + responseBody);
}
response.reset();

View File

@ -710,6 +710,49 @@ TEST(TokenCredentialImpl, MaxValues)
std::exception);
}
TEST(TokenCredentialImpl, AuthErrorResponse)
{
std::string const errorJson
= "{\"error\":\"invalid_request\","
"\"error_description\":\"AADSTS90014: "
"The required field 'scope' is missing from the credential. "
"Ensure that you have all the necessary parameters for the login request. "
"Trace ID: 01234567-89ab-cdef-0123-456789abcdef "
"Correlation ID: fedcba98-7654-3210-0123-456789abcdef "
"Timestamp: 2023-11-30 00:51:37Z\","
"\"error_codes\":[90014],"
"\"timestamp\":\"2023-11-30 00:51:37Z\","
"\"trace_id\":\"01234567-89ab-cdef-0123-456789abcdef\","
"\"correlation_id\":\"fedcba98-7654-3210-0123-456789abcdef\","
"\"error_uri\":\"https://login.microsoftonline.com/error?code=90014\"}";
try
{
using Azure::Core::Http::HttpStatusCode;
std::vector<std::string> const testScopes;
CredentialTestHelper::TokenRequestSimulationServerResponse testResponse;
testResponse.StatusCode = HttpStatusCode::BadRequest;
testResponse.Body = errorJson;
static_cast<void>(CredentialTestHelper::SimulateTokenRequest(
[](auto transport) {
TokenCredentialOptions options;
options.Transport.Transport = transport;
return std::make_unique<TokenCredentialImplTester>(
HttpMethod::Delete, Url("https://outlook.com/"), options);
},
{testScopes},
{testResponse}));
EXPECT_TRUE(!"TokenCredentialImpl should throw given the response above.");
}
catch (AuthenticationException const& ex)
{
EXPECT_EQ(ex.what(), "GetToken(): error response: 400 Test\n\n" + errorJson);
}
}
TEST(TokenCredentialImpl, Diagnosability)
{
using Azure::Core::Diagnostics::Logger;