microsoft-identity-web icon indicating copy to clipboard operation
microsoft-identity-web copied to clipboard

response.EnsureSuccessStatusCode is preventing validation errors being sent back to the calling code.

Open WhoopieMonster opened this issue 1 year ago • 5 comments

Microsoft.Identity.Web Library

Microsoft.Identity.Web

Microsoft.Identity.Web version

3.2.0

Web app

Sign-in users

Web API

Protected web APIs call downstream web APIs

Token cache serialization

In-memory caches

Description

When calling a downstream api I would expect to receive the payload regardless of the success status of the http call. The use of response.EnsureSuccessStatusCode is preventing this from happening.

There are plenty of scenarios where this behaviour should be supported, the most obvious being validation errors.

Reproduction steps

Intentionally call a downstream api with an invalid payload causing a failure, such as model validation, generating a non-successful http status code.

Error message

A new HttpRequestError is thrown.

Id Web logs

No response

Relevant code snippets

var result = await downstreamApi.PostForUserAsync<object, object>(
"my_api",
data,
options =>
{
    options.RelativePath = $"my_api/my_data";
});

Regression

No response

Expected behavior

Alongside the exception I would still expect to receive the payload from the downstream api, allowing me the freedom to decide what to do with it.

WhoopieMonster avatar Oct 05 '24 11:10 WhoopieMonster

Appreciate this is light on samples - but the issue is very straightforward.

WhoopieMonster avatar Oct 05 '24 11:10 WhoopieMonster

You should be able to use the generic method CallApiForAppAsync with the proper method settings in downstreamApiOptions to receive the actual response. Had a similar issue too, took that route, and that seemed to work for my case.

Though, I found this as a viable alternative by searching through GitHub issues and finding the recommendation. It might be a good change to make this more obvious, but I'm not exactly sure how.

zminot avatar Oct 10 '24 19:10 zminot

@zminot unfortunately if you choose one of the generic overloads eg CallApiForAppAsync<TInput, TOutput> where the SDK code then calls the deserialisation methods, these methods check for a HTTP success status code and throw an exception if not. So in the case of a 400 Bad Request where I return validation errors in an object, I now can't get that response body back from the DownstreamApi object, which is frustrating.

Edit: See here https://github.com/AzureAD/microsoft-identity-web/blob/e76c1e5220f3004163102e5349998398e4aee126/src/Microsoft.Identity.Web.DownstreamApi/DownstreamApi.cs#L405-L421

richsage avatar May 11 '25 13:05 richsage

We are also hitting this which significantly lowers the value of the otherwise very helpful overloads. I guess for now we need to do the boilerplate ourselves and use the less valuable overloads, if we want to return error messages or similar in a non success http response.

rvplauborg avatar Oct 29 '25 20:10 rvplauborg

I just came back to this and noticed that it has been tagged perhaps incorrectly as documentation when I would argue this is potentially a bug or feature enhancement to enable getting the raw payload without the SDK making assumptions around status codes. @jennyf19 I noticed you did the original tagging - is it possible to re-review?

richsage avatar Oct 29 '25 21:10 richsage