简体   繁体   中英

Which Microsoft Graph authentication provider to use for ChatMessage in C#

I am very new to Teams and Microsoft Graph.

My aim: To send a message to a channel from a C# desktop app.

I think I've made some progress, I got the Team ID, Channel ID and Client ID. I installed the Graph Beta package from NuGet.

string clientId = "xxxSomeIDxxx";

        IPublicClientApplication publicClientApplication = PublicClientApplicationBuilder
        .Create(clientId)
        .Build();

        GraphServiceClient graphClient = new GraphServiceClient(authProvider);

        var chatMessage = new ChatMessage
        {
            Subject = null,
            Body = new ItemBody
            {
                ContentType = BodyType.Html,
                Content = "<attachment id=\"74d20c7f34aa4a7fb74e2b30004247c5\"></attachment>"
            },
            Attachments = new List<ChatMessageAttachment>()
        {
             new ChatMessageAttachment
            {
                Id = "74d20c7f34aa4a7fb74e2b30004247c5",
                ContentType = "application/vnd.microsoft.card.thumbnail",
                ContentUrl = null,
                Content = "Here is some body text.",
                Name = null,
                ThumbnailUrl = null
             }
             }
        };

        await graphClient.Teams["xxxSomeIDxxx"].Channels["xxSomeIdxxx"].Messages
        .Request()
        .AddAsync(chatMessage);

I dont know how to make the Authentication Provider.

By looking at it it seems like this is the right one:

    InteractiveAuthenticationProvider authProvider = new InteractiveAuthenticationProvider(publicClientApplication, scopes);

But scopes is undefined.

Can someone please assist and tell met which Microsoft Graph authentication provider to use for ChatMessage in C#

I use Visual studio 2017 C# windows form app Microsoft Teams

The interface IAuthenticationProvider only has a single method:

Task AuthenticateRequestAsync(HttpRequestMessage request);

We use a simple AuthenticationProvider that looks like this:

public class AuthenticationProvider : IAuthenticationProvider
{
    private readonly string _accessToken;

    public AuthenticationProvider(string accessToken)
    {
        _accessToken = accessToken;
    }

    public Task AuthenticateRequestAsync(HttpRequestMessage request)
    {
        request.Headers.Add("Authorization", $"Bearer {_accessToken}");
        return Task.CompletedTask;
    }
}

We use this to save our access token in MemoryCache since we have a service calling the Graph API and not a specific user. I hope it can give some guidance anyway:

using Microsoft.Extensions.Caching.Memory;
using Microsoft.Graph;
using Microsoft.Identity.Client;
using Project.Repository.Models;
using Project.Repository.Models.Azure.ADB2C;
using Project.Repository.Models.Constants;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace Project.Repository.Services.External
{
    public class GraphApiService
    {
        private readonly IHttpClientFactory _clientFactory;
        private readonly IMemoryCache _memoryCache;
        private readonly Settings _settings;
        private readonly string _accessToken;

        public GraphApiService(IHttpClientFactory clientFactory, IMemoryCache memoryCache, Settings settings)
        {
            _clientFactory = clientFactory;
            _memoryCache = memoryCache;
            _settings = settings;

            string graphApiAccessTokenCacheEntry;

            // Look for cache key.
            if (!_memoryCache.TryGetValue(CacheKeys.GraphApiAccessToken, out graphApiAccessTokenCacheEntry))
            {
                // Key not in cache, so get data.
                var adb2cTokenResponse = GetAccessTokenAsync().GetAwaiter().GetResult();

                graphApiAccessTokenCacheEntry = adb2cTokenResponse.access_token;

                // Set cache options.
                var cacheEntryOptions = new MemoryCacheEntryOptions()
                    .SetAbsoluteExpiration(TimeSpan.FromSeconds(adb2cTokenResponse.expires_in));

                // Save data in cache.
                _memoryCache.Set(CacheKeys.GraphApiAccessToken, graphApiAccessTokenCacheEntry, cacheEntryOptions);
            }

            _accessToken = graphApiAccessTokenCacheEntry;
        }

        //TODO - Call this method and refresh cache when a new user is added
        public async Task<List<Adb2cUser>> GetAllUsers(bool refreshCache = false)
        {
            List<Adb2cUser> adb2cUsers;

            if (refreshCache)
            {
                _memoryCache.Remove(CacheKeys.Adb2cUsers);
            }

            // Look for cache key.
            if (!_memoryCache.TryGetValue(CacheKeys.Adb2cUsers, out adb2cUsers))
            {
                // Key not in cache, so get data.
                adb2cUsers = new List<Adb2cUser>();

                var authProvider = new AuthenticationProvider(_accessToken);

                GraphServiceClient graphClient = new GraphServiceClient(authProvider);

                var users = await graphClient.Users
                    .Request()
                    .GetAsync();

                foreach (var user in users)
                {
                    var adb2cUser = new Adb2cUser()
                    {
                        Id = Guid.Parse(user.Id),
                        GivenName = user.GivenName,
                        FamilyName = user.Surname,
                    };
                    adb2cUsers.Add(adb2cUser);
                }

                // Set cache options.
                var cacheEntryOptions = new MemoryCacheEntryOptions()
                    //Get new values every hour
                    .SetAbsoluteExpiration(TimeSpan.FromHours(1));

                // Save data in cache.
                _memoryCache.Set(CacheKeys.Adb2cUsers, adb2cUsers, cacheEntryOptions);
            }

            return adb2cUsers;
        }

        private async Task<Adb2cTokenResponse> GetAccessTokenAsync()
        {
            var client = _clientFactory.CreateClient();

            var kvpList = new List<KeyValuePair<string, string>>();
            kvpList.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
            kvpList.Add(new KeyValuePair<string, string>("client_id", _settings.AzureAdB2C.ClientId));
            kvpList.Add(new KeyValuePair<string, string>("scope", "https://graph.microsoft.com/.default"));
            kvpList.Add(new KeyValuePair<string, string>("client_secret", _settings.AzureAdB2C.ClientSecret));

#pragma warning disable SecurityIntelliSenseCS // MS Security rules violation
            var req = new HttpRequestMessage(HttpMethod.Post, $"https://login.microsoftonline.com/{_settings.AzureAdB2C.Domain}/oauth2/v2.0/token")
            { Content = new FormUrlEncodedContent(kvpList) };
#pragma warning restore SecurityIntelliSenseCS // MS Security rules violation

            using var httpResponse = await client.SendAsync(req);

            var response = await httpResponse.Content.ReadAsStringAsync();

            httpResponse.EnsureSuccessStatusCode();

            var adb2cTokenResponse = JsonSerializer.Deserialize<Adb2cTokenResponse>(response);

            return adb2cTokenResponse;
        }
    }

    public class AuthenticationProvider : IAuthenticationProvider
    {
        private readonly string _accessToken;

        public AuthenticationProvider(string accessToken)
        {
            _accessToken = accessToken;
        }

        public Task AuthenticateRequestAsync(HttpRequestMessage request)
        {
            request.Headers.Add("Authorization", $"Bearer {_accessToken}");
            return Task.CompletedTask;
        }
    }
}

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