简体   繁体   中英

Microsoft Graph API. Getting user activity

Currently I'm trying to create user activity from uwp application. But every time I encounter this response.

{
    "error": {
        "code": "AuthenticationError",
        "message": "Error authenticating with resource",
        "innerError": {
            "date": "2022-12-28T09:20:16",
            "request-id": "some id",
            "client-request-id": "some id"
        }
    }
}

Here is my c# code example. Request content string was taken from microsoft docs

public sealed class UserActivityProvider : IUserActivityProvider
{
    private const string activityId = "SendMessageUserActivity";
    private static HttpClient httpClient = new HttpClient();

    public UserActivityProvider()
    {
    }

    private async Task<string> GetAccessTokenAsync(Account account)
    {
        var accessToken = string.Empty;

        var publicClientApplication = PublicClientApplicationBuilder.Create(MicrosoftConstants.ClientId)
           .WithRedirectUri(MicrosoftConstants.RedirectUri)
           .Build();

        var scopes = new string[]
        {
            "UserActivity.ReadWrite.CreatedByApp"
        };

        AuthenticationResult? authToken = null;

        try
        {
            authToken = await publicClientApplication.AcquireTokenSilent(scopes, account.Email).ExecuteAsync();
        }
        catch (Exception)
        {
            authToken = await publicClientApplication.AcquireTokenInteractive(scopes).ExecuteAsync();
        }

        if (authToken != null)
        {
            accessToken = authToken.AccessToken;
        }

        return accessToken;
    }

    public async Task CreateUserActivityAsync(Account account, CreatingMessageUserActivityParameters userActivityParameters)
    {
        var accessToken = await GetAccessTokenAsync(account);
        if (accessToken != string.Empty)
        {
            var contentForCreatingActivity = new StringContent("{\r\n  \"appActivityId\": \"SendMessageUserActivity\",\r\n  \"activitySourceHost\": \"https://www.contoso.com\",\r\n  \"userTimezone\": \"Africa/Casablanca\",\r\n  \"appDisplayName\": \"Contoso, Ltd.\",\r\n  \"activationUrl\": \"https://www.contoso.com/article?id=12345\",\r\n  \"contentUrl\": \"https://www.contoso.com/article?id=12345\",\r\n  \"fallbackUrl\": \"https://www.contoso.com/article?id=12345\",\r\n  \"contentInfo\": {\r\n    \"@context\": \"https://schema.org\",\r\n    \"@type\": \"Article\",\r\n    \"author\": \"Jennifer Booth\",\r\n    \"name\": \"How to Tie a Reef Knot\"\r\n  },\r\n  \"visualElements\": {\r\n    \"attribution\": {\r\n      \"iconUrl\": \"https://www.contoso.com/icon\",\r\n      \"alternateText\": \"Contoso, Ltd.\",\r\n      \"addImageQuery\": false\r\n    },\r\n    \"description\": \"How to Tie a Reef Knot. A step-by-step visual guide to the art of nautical knot-tying.\",\r\n    \"backgroundColor\": \"#ff0000\",\r\n    \"displayText\": \"Contoso How-To: How to Tie a Reef Knot\",\r\n    \"content\": {\r\n      \"$schema\": \"https://adaptivecards.io/schemas/adaptive-card.json\",\r\n      \"type\": \"AdaptiveCard\",\r\n      \"body\": [\r\n        {\r\n          \"type\": \"TextBlock\",\r\n          \"text\": \"Contoso MainPage\"\r\n        }\r\n      ]\r\n    }\r\n  }\r\n}", Encoding.UTF8, "application/json");
            httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
            var response = await httpClient.PutAsync($"https://graph.microsoft.com/beta/me/activities/{activityId}", contentForCreatingActivity);
            var stringifiedResponse = await response.Content.ReadAsStringAsync();
        }
    }
}

And here is also get method for retrieving all activities and it's also return bad request

public async Task<string?> IsUserActivityExistsAsync(Account account)
{
    string? resultSubject = null;

    var accessToken = await GetAccessTokenAsync(account);
    if (accessToken != string.Empty)
    {
        httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
        var response = await httpClient.GetAsync("https://graph.microsoft.com/v1.0/me/activities");
        var stringifiedResponse = await response.Content.ReadAsStringAsync();
    }

    return resultSubject;
}

All articles referencing that I have to provide correct scope but I took that scope from official microsoft docs and there wouldn't be a mistake.

Response for getting activities

{
  "error": {
    "code": "UnknownError",
    "message": "{\"ErrorCode\":2,\"ErrorMessage\":\"Substrate operation failed. Url: https://substrate.office.com/api/v2.0/users('******(73)')/CurrentCollections('******(10)') Status: Unauthorized. Error Code: invalid_tenant Error Message: The tenant for tenant guid 'tenant' does not exist., SubstrateError: null\"}",
    "innerError": {
      "date": "2022-12-29T05:44:57",
      "request-id": "id",
      "client-request-id": "id"
    }
  }
}

Response for adding activities

{
  "error": {
    "code": "UnknownError",
    "message": "{\"ErrorCode\":35,\"ErrorMessage\":\"General error occurred. Contact product team.\"}",
    "innerError": {
      "date": "2022-12-29T05:59:02",
      "request-id": "id",
      "client-request-id": "id"
    }
  }
}

Please make sure that UserActivity.ReadWrite.CreatedByApp MS Graph API permissions are assigned to your app in Azure AD as Delegated type (not Application)

As you said you are getting empty data when you decoded the access token in jwt.ms, which means you are doing something wrong while acquiring access token, follow the doc to get token via Interactive provider , and then again check by decoding in jwt.ms.

var scopes = new[] { "User.Read" };

// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";

// Value from app registration
var clientId = "YOUR_CLIENT_ID";

// using Azure.Identity;
var options = new InteractiveBrowserCredentialOptions
{
    TenantId = tenantId,
    ClientId = clientId,
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
    // MUST be http://localhost or http://localhost:PORT
    // See https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/System-Browser-on-.Net-Core
    RedirectUri = new Uri("http://localhost"),
};

// https://learn.microsoft.com/dotnet/api/azure.identity.interactivebrowsercredential
var interactiveCredential = new InteractiveBrowserCredential(options);

var graphClient = new GraphServiceClient(interactiveCredential, scopes);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM