msgraph-sdk-dotnet icon indicating copy to clipboard operation
msgraph-sdk-dotnet copied to clipboard

Model errors when using the Graph API with access token obtained through code

Open NicolasDemarbaix opened this issue 4 years ago • 18 comments

Describe the bug When trying to perform certain mail actions (e.g. Update a message) I am receiving model errors such as: { "error": { "code": "RequestBodyRead", "message": "The property 'isRead' does not exist on type 'Microsoft.OutlookServices.Message'. Make sure to only use property names that are defined by the type or mark the type as open type. REST APIs for this mailbox are currently in preview. You can find more information about the preview REST APIs at https://dev.outlook.com/.", "innerError": { "date": "2021-08-25T14:15:45", "request-id": "866b05b6-3200-489c-a547-fb6d9d022ac4", "client-request-id": "866b05b6-3200-489c-a547-fb6d9d022ac4" } } }

However I only see these issues when using an access token that was obtained through code. When I use the access token that is available on any related calls in the Graph Explorer in my own code the action works fine.

To Reproduce Steps to reproduce the behavior: I'm executing the following code to obtain an access token and execute a Mark email as read action:

  1. Fetch access token (Auth Code Grant Flow): `
    var authority = $"https://login.microsoftonline.com/";

         application = PublicClientApplicationBuilder.Create("<client-id>")
             .WithAuthority(authority)
             .WithDefaultRedirectUri()
             .Build();
    
         AuthenticationResult result;
    
         try
         {
             var accounts = await application.GetAccountsAsync();
             result = await application.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();
         }
         catch (MsalUiRequiredException ex)
         {
             result = await application.AcquireTokenInteractive(scopes).WithClaims(ex.Claims).ExecuteAsync();
         }
    
         return result.AccessToken;
    

`

  1. Link access token to Graph Service Client: ` var serviceClient = new GraphServiceClient("https://graph.microsoft.com/v1.0/", new DelegateAuthenticationProvider(async (requestMessage) => { requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await SignIn(configuration, scopes)); }));

         return await Task.FromResult(serviceClient);
    

`

  1. Execute Mark As Read action: ` var scopes = new string[] { "https://graph.microsoft.com/.default" };

         var client = await LoadServiceClient(null, scopes);
    
         var message = new Message
         {
             IsRead = true
         };
    
         var response = await client.Me.Messages["message-id"]
             .Request().Select("IsRead").UpdateAsync(message);
    

`

After executing this action I see the error message described above. When I try the same action through the Graph Explorer or use the access token found on the Graph Explorer it works as expected.

Expected behavior Executing the code above works regardless of using the access token found in the Graph Explorer or using an access token obtained through code.

** Environment ** Testing on following environments: Mac OS Big Sur v11.2.1 with Visual Studio for Mac NET SDK: v5.0 Microsoft.Graph: v4.3.0

Microsoft Windows Server 2021 R2 with Visual Studio 2017 NET SDK: v4.7.2 Microsoft.Graph: v4.3.0

Additional context We currently have a Hybrid setup environment (Azure AD + on-premise Exchange Server). It is not possible to migrate any mailboxes to Office 365 at this time.

The contents (claims) of the access token obtained through the Graph Explorer and through code are identical with the exception of the 'platf' claim and the 'signin_state' claim

AB#10872

NicolasDemarbaix avatar Aug 26 '21 08:08 NicolasDemarbaix

Hey @NicolasDemarbaix,

Thanks for raising this issue.

I notice for the .Net app, the scopes are specified as

var scopes = new string[] { "https://graph.microsoft.com/.default" };

However, the docs specify that you would need the Mail.ReadWrite scope.

Are you able to decode the token from the app here to confirm if the specified scope is present in your token. Scopes should be in the scp property as below.

image

If it helps you can compare the same with the token from graph explorer (this can be copied from the Access Token tab).

andrueastman avatar Aug 30 '21 06:08 andrueastman

Hi @andrueastman

Thank you for your answer. From what I understood in the docs, specifying the scope "https://graph.microsoft.com/.default" indicates that all the related scopes of the client app should be used. Deconstructing the access token I receive through my code also shows this, as the "scp" (scope) claim contains the following items: "email Mail.Read Mail.ReadBasic Mail.ReadWrite Mail.Send openid profile User.Read".

When deconstructing the access token I copied from the graph explorer, I see the some items in the "scp" claim: "Mail.Read Mail.ReadBasic Mail.ReadWrite Mail.Send openid profile User.Read email"

I also tried specifying the scope "Mail.ReadWrite" in my code (instead of https://graph.microsoft.com/.default"), however this did not change the outcome as the scp claim still contained all items defined above.

NicolasDemarbaix avatar Aug 31 '21 11:08 NicolasDemarbaix

Hey @NicolasDemarbaix,

Are you able to confirm that your hybrid setup meets the requirements below? https://docs.microsoft.com/en-us/graph/hybrid-rest-support

Also, if you are still able to replicate this, are you able to obtain and share the "client-request-id" of the successful call via Graph Explorer(this should be in the Response Headers tab) and also the failing one with code? This will help in giving feedback to the relevant team as support for hybrid environments is still in preview.

andrueastman avatar Sep 13 '21 08:09 andrueastman

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

ghost avatar Sep 17 '21 09:09 ghost

Hi @andrueastman ,

Our IT department confirmed that all requirements described in the page you posted (hybrid rest setup) are met.

At the moment I can still replicate this issue. Below you can find the client request id's for both the successful call via the Graph explorer and the failing call via code.

  • Graph Explorer client request id: 2d229343-b595-84ac-3d55-be0e0f704daa
  • Code call client request id: c8cc36dd-86d8-443f-af39-982101398ba2

NicolasDemarbaix avatar Sep 19 '21 07:09 NicolasDemarbaix

Thanks @NicolasDemarbaix,

Are you able to provide the approximate timestamps of the requests as well? This will help in finding the logs to associate with the request ids to forward to the relevant team.

andrueastman avatar Sep 20 '21 05:09 andrueastman

Hi @andrueastman ,

I executed new calls to collect the client request id's around the same time I posted my comment. So I presume both calls happened somewhere between 09:15 AM and 09:45 AM (GMT+1) on September 19th.

NicolasDemarbaix avatar Sep 20 '21 07:09 NicolasDemarbaix

Thanks @NicolasDemarbaix,

I just took at the logs from the request ids and I was able to find some error information.

Are you able to reproduce the issue if you set the odata.type to null on the message object when sending the request? See below.

     var message = new Message
     {
         ODataType = null, // add this
         IsRead = true
     };

     var response = await client.Me.Messages["message-id"]
         .Request().Select("IsRead").UpdateAsync(message);

Also, are you able to replicate the error if you add the "@odata.type" property to the payload like the example below on Graph Explorer?

POST https://graph.microsoft.com/v1.0/me/sendMail
{
    "message": {
        "@odata.type": "#microsoft.graph.message",
        "subject": "Meet for lunch?",
        "body": {
            "contentType": "Text",
            "content": "The new cafeteria is open."
        },
        "toRecipients": [
            {
                "emailAddress": {
                    "address": "[email protected]"
                }
            }
        ]
    }
}

I ask this because the @odata.type property is the only difference between the two requests (Though they both work from my side and the hope is to narrow down if it's only affecting onPremise inboxes)

andrueastman avatar Sep 20 '21 08:09 andrueastman

Hi @andrueastman ,

When I add "@odata.type": "#microsoft.graph.message" to the request body in the Graph Explorer the request still works (client-request-id: 7e0ec69d-e59f-264e-ca7f-94f37f73737a, timestamp = 1:32 PM GMT+1).

When adding the property ODataType = null to the request body via code I'm still seeing errors (client-request-id: b9ccd115-c3a3-4a1a-9962-a643f94ab2f3, timestamp 1:34 PM GMT+1).

However the contents of the error do differ. The error I'm seeing now is the following:

The property 'isRead' does not exist on type 'Microsoft.OutlookServices.Message'. Make sure to only use property names that are defined by the type or mark the type as open type. REST APIs for this mailbox are currently in preview. You can find more information about the preview REST APIs at https://dev.outlook.com/.

The original error message in the call with ODataType = null is:

A type named 'microsoft.graph.message' could not be resolved by the model. When a model is available, each type name must resolve to a valid type. REST APIs for this mailbox are currently in preview. You can find more information about the preview REST APIs at https://dev.outlook.com/.

NicolasDemarbaix avatar Sep 20 '21 11:09 NicolasDemarbaix

Hi @andrueastman ,

It's been 2 months since I last received an update about this issue.

Are there any new developments regarding the above?

NicolasDemarbaix avatar Nov 20 '21 12:11 NicolasDemarbaix

Hi @NicolasDemarbaix .

Can you confirm whether you are still facing the same issue with the latest version of the SDK?

maisarissi avatar Feb 24 '22 22:02 maisarissi

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

ghost avatar Feb 28 '22 23:02 ghost

@maisarissi,

Last time I checked this issue still existed. I will try to run my tests again to confirm whether this is still the case with the latest version of the SDK released last week.

If so I will provide the necessary details for further investigation

NicolasDemarbaix avatar Mar 01 '22 09:03 NicolasDemarbaix

Hi @maisarissi ,

I finally found the time to fully test the above, my apologies for the delay.

When executing this code with the latest Microsoft.Graph package (4.19.0) under .NET 6.0 I am still seeing the samen issues. Below are the errors I am receiving along with the associated timestamps and request IDs.


Option 1: When specifying no ODataType property I got the following error: Code: RequestBodyRead Message: A type named 'microsoft.graph.message' could not be resolved by the model. When a model is available, each type name must resolve to a valid type. REST APIs for this mailbox are currently in preview. You can find more information about the preview REST APIs at https://dev.outlook.com/. Inner error: AdditionalData: date: 2022-03-04T09:54:23 request-id: cef1f70b-9d5f-4ed7-a8dd-6f64bdbf57cd client-request-id: cef1f70b-9d5f-4ed7-a8dd-6f64bdbf57cd


Option 2: When specifying ODataType = null in the Message object, I got the following error: Code: RequestBodyRead Message: The property 'isRead' does not exist on type 'Microsoft.OutlookServices.Message'. Make sure to only use property names that are defined by the type or mark the type as open type. REST APIs for this mailbox are currently in preview. You can find more information about the preview REST APIs at https://dev.outlook.com/. Inner error: AdditionalData: date: 2022-03-04T09:56:40 request-id: c4f2d382-82bc-4025-ad04-062be00b4169 client-request-id: c4f2d382-82bc-4025-ad04-062be00b4169


Option 3: When specifying ODataType = "#microsoft.graph.message", I got the following error: Code: RequestBodyRead Message: A type named 'microsoft.graph.message' could not be resolved by the model. When a model is available, each type name must resolve to a valid type. REST APIs for this mailbox are currently in preview. You can find more information about the preview REST APIs at https://dev.outlook.com/. Inner error: AdditionalData: date: 2022-03-04T09:57:44 request-id: d08574cd-048c-430b-85ad-726d7ea9f9c6 client-request-id: d08574cd-048c-430b-85ad-726d7ea9f9c6

NicolasDemarbaix avatar Mar 04 '22 10:03 NicolasDemarbaix

@NicolasDemarbaix

Looking at the original request, I wonder if the select statement is causing this. The select statement should be ignored by the service since it isn't expected to be there. It may be that the service is encountering an error because of it. Can you remove the select statement and see if the error persists?

var response = await client.Me.Messages["message-id"].Request().Select("IsRead").UpdateAsync(message);

MIchaelMainer avatar Mar 04 '22 17:03 MIchaelMainer

@MIchaelMainer

Removing the select statement does not appear to have any effect. I executed the following command: await client.Me.Messages["<message-id>"].Request().UpdateAsync(message);

I'm still getting the same error message: Code: RequestBodyRead Message: A type named 'microsoft.graph.message' could not be resolved by the model. When a model is available, each type name must resolve to a valid type. REST APIs for this mailbox are currently in preview. You can find more information about the preview REST APIs at https://dev.outlook.com/. Inner error: AdditionalData: date: 2022-03-07T07:47:45 request-id: cd384d37-d6d2-4fa4-9c1f-00cc83aab9e0 client-request-id: cd384d37-d6d2-4fa4-9c1f-00cc83aab9e0 ClientRequestId: cd384d37-d6d2-4fa4-9c1f-00cc83aab9e0

NicolasDemarbaix avatar Mar 07 '22 07:03 NicolasDemarbaix

@NicolasDemarbaix

I apologize for this scenario. The hybrid scenario raises mysterious problems like this one.

After executing this action I see the error message described above. When I try the same action through the Graph Explorer or use the access token found on the Graph Explorer it works as expected.

Are you using the same user account in both scenarios?

MIchaelMainer avatar Mar 08 '22 22:03 MIchaelMainer

@MIchaelMainer

I can confirm that I am using the same account in both scenario's. To be sure I tested the scenario's again:


Scenario 1: Sending a patch request to https://graph.microsoft.com/v1.0/me/messages/ through the Graph Explorer successfully marks the email as read. Body used in request: { "isRead": true }


Scenario 2: Sending an update of the message through the Graph API SDK obtaining an access token through a PublicApplication instance (AcquireTokenInteractive) fails


Scenario 3: Executing the same code through the Graph API SDK but using the access token that is available on the Graph Explorer does work.


The only difference I can spot between the access token generated through code and the access token obtained through the Graph explorer are:

  • aud claim:
    • Code: https://graph.microsoft.com
    • Graph Explorer: 00000003-0000-0000-c000-000000000000
  • appid:
    • Code: ID of our app registration on our Azure portal
    • Graph Explorer: ID of graph explorer app registration

NicolasDemarbaix avatar Mar 10 '22 09:03 NicolasDemarbaix

Hi,

It's been a while since this issue received any response. As we are still facing this issue I was wondering what the status of this issue is.

To be sure I already tested the above scenario with the latest stable version of the Microsoft.Graph package (4.47.0 at the time of writing) but the issue still exists.

NicolasDemarbaix avatar Nov 14 '22 08:11 NicolasDemarbaix

Hi all,

I am facing the exact same situation when trying to create events for the logged in user in my ASP.NET Core web app.

date: 2023-02-08T15:59:02 UTC request-id: e2c015d1-53fc-488a-9fc9-d1680623ea55 client-request-id: e2c015d1-53fc-488a-9fc9-d1680623ea55

Getting/listing events works fine in the web app, creating events via Graph Explorer works fine. Creating events in my web app does not. Also tried the ODataType workaround, and it behaves the same just like in Nicolas' case.

Tried all this with the Microsoft.Graph package v4.53.0.

Doing the HTTP POST via curl works fine when using the token from the Graph Explorer, but it does not work with the token that I got in the web app. Claims/permissions are set up properly....

cars10w avatar Feb 08 '23 16:02 cars10w

Ok, this has been resolved for my usecase. We are in a hybrid scenario. When trying to create an event to an on-premise user/mailbox, I get the erroneous behaviour mentioned above. It works fine when creating an event for cloud-users or cloud-groups. Graph API access for on-premise Exchange is deprecated anyway, hence avoiding this.

Why it is working with the Graph Explorer also for on-premise users, remains a mystery....

cars10w avatar Feb 09 '23 10:02 cars10w

Hi everyone,

Seeing that the access to on-premise and/or hybrid setups from the Graph API has been deprecated and will be completely removed in the next couple of weeks, I'm closing this issue.

NicolasDemarbaix avatar Feb 09 '23 15:02 NicolasDemarbaix