microsoftgraph / msgraph-beta-sdk-java

Microsoft Graph Beta Java SDK
https://docs.microsoft.com/en-us/graph/sdks/use-beta?tabs=Java
MIT License
24 stars 8 forks source link

Permissions error response not deserialized correctly #918

Open jeremymailen opened 3 months ago

jeremymailen commented 3 months ago

Expected behavior

API calls with errors should return a useable error response.

Actual behavior

An exception is thrown while parsing the permission error response:

com.microsoft.graph.beta.models.odataerrors.ODataError: 
    at com.microsoft.graph.beta.models.odataerrors.ODataError.createFromDiscriminatorValue(ODataError.java:36) ~[microsoft-graph-beta-6.5.1.jar:na]
    at com.microsoft.kiota.serialization.JsonParseNode.getObjectValue(JsonParseNode.java:211) ~[microsoft-kiota-serialization-json-1.1.2.jar:na]
    at com.microsoft.kiota.http.OkHttpRequestAdapter.lambda$throwIfFailedResponse$0(OkHttpRequestAdapter.java:674) ~[microsoft-kiota-http-okHttp-1.1.2.jar:na]
    at com.microsoft.kiota.ApiExceptionBuilder.<init>(ApiExceptionBuilder.java:26) ~[microsoft-kiota-abstractions-1.1.2.jar:na]
    at com.microsoft.kiota.http.OkHttpRequestAdapter.throwIfFailedResponse(OkHttpRequestAdapter.java:673) ~[microsoft-kiota-http-okHttp-1.1.2.jar:na]
    at com.microsoft.kiota.http.OkHttpRequestAdapter.send(OkHttpRequestAdapter.java:281) ~[microsoft-kiota-http-okHttp-1.1.2.jar:na]
    at com.microsoft.graph.beta.security.informationprotection.sensitivitylabels.SensitivityLabelsRequestBuilder.get(SensitivityLabelsRequestBuilder.java:120) ~[microsoft-graph-beta-6.5.1.jar:na]

Steps to reproduce the behavior

baywet commented 3 months ago

Hi @jeremymailen Thanks for reporting this. Can you share a code snippet of the request you're making please?

jeremymailen commented 3 months ago

Sure, here's more repro detail:

val credential =ClientSecretCredentialBuilder()
        .tenantId(params.tenant)
        .clientId(params.clientId)
        .clientSecret(params.clientSecret)
        .build()

val scopes = arrayOf("https://graph.microsoft.com/.default")
val allowedHosts = arrayOf("graph.microsoft.com")
val auth = AzureIdentityAuthenticationProvider(credential, allowedHosts, *scopes)
val client = GraphServiceClient(auth)

val labelResponse = client.security().informationProtection().sensitivityLabels()
    .get { request -> request.queryParameters.top = 99 }

This throws the exception above.

Note that making this call manually with an http client reveals the error response actually looks like this:

403 Forbidden
"{"error":{"code":"UnknownError","message":"","innerError":{"date":"2024-04-09T17:16:04","request-id":"84d6f6a5-68ae-4b62-865c-4137a51f5ad6","client-request-id":"84d6f6a5-68ae-4b62-865c-4137a51f5ad6"}}}"
baywet commented 3 months ago

Thanks for the additional information. It seems to be failing on instantiating the error object which is strange. Do you have other call either succeeding, or failing while throwing a properly parsed exception in this application?

As for the service error itself, it's not super useful, I'd encourage reaching out to the support or asking a question on Microsoft Q&A with the Microsoft Graph tag.

jeremymailen commented 3 months ago

The successful calls work with this msgraph client and serialize / deserialize objects correctly. So the happy path works fine. And also once we add the InformationProtectionPolicy.Read.All permission to the app registration, things work from then on, so we know the source of the error and how to fix it.

The bug remains that this client doesn't correctly parse that error that gets returned. Perhaps there's a bug on the MS Graph server side where it should be returning a more specific error, but that's not for me to say :).

baywet commented 3 months ago

Thanks for the additional information. If you simply call deserialize with the string payload and the ODataErrorFactory as parameters, do you run into the same issue?

jeremymailen commented 3 months ago

I think the development will be better equipped to troubleshoot from here as I understand code generation from specs is used to produce the implementation. Should be straightforward to reproduce.

baywet commented 3 months ago

So are you saying you're not going to try to repro just calling the deserialization code on the payload?

jeremymailen commented 3 months ago

Are you unable to repro the issue? I think it's reproducible at least on any API call where your app registration doesn't have permission to make the call.