1

I have been working on an Azure Function. The function is daemon that doesn't require user interaction. Therefore, it uses application permissions to consume Microsoft Graph.

The idea is to have only one instance of Graph Service Client that will be consumed by all the instances of that Azure Functions. To do so, I have created a singleton class.

Considering that Microsoft.Graph.Auth is in preview, and will never go out preview, I have opted to use Microsoft.Identity package instead. I pass a delegate to the graph service client, that acquires token for the client. If the token is expired, the new token gets acquired automatically. AcquireTokenForClient(scopes) returns the same token again, however, if it is about to expire, it gets the new token.

  1. The question is that is it the right approach to handle the token refresh, considering there can be multiple instances of Azure Function running?
  2. Secondly, is it the right way to create authentication provider for graph service client using Microsoft.Identity? Or is there a better way?
  3. Lastly, is it a good idea to use Microsoft Graph SDK at all? Because, the documentation is using Microsoft.Graph.Auth which according to Microsoft will never go out of preview. There isn't much documentation of how and what to do instead.

My Code:

    public class MSGraphAuth
    {
        private static MSGraphAuth _graphAuth;
        private static GraphServiceClient _graphClient;
        private static readonly object _lock = new object();

        private MSGraphAuth() { }

        public static MSGraphAuth GraphAuth
        {
            get
            {
                if (_graphAuth == null)
                {
                    lock (_lock)
                    {
                        if (_graphAuth == null)
                        {
                            _graphAuth = new MSGraphAuth();
                            _graphAuth.InitializeGraphClient();
                        }
                    }
                }

                return _graphAuth;
            }
        }

        public GraphServiceClient GraphClient
        {
            get
            {
                return _graphClient;
            }
        }

        void InitializeGraphClient()
        {
            string authority = "{authority}";

            IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
            .Create(AppSettings.MSGRAPHCLIENTID)
            .WithAuthority(authority)
            .WithClientSecret(AppSettings.MSGRAPHCLIENTSECRET)
            .Build();

            _graphClient = new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) =>
            {

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

                var authResult = await confidentialClientApplication.AcquireTokenForClient(scopes).ExecuteAsync();

                requestMessage
                    .Headers
                    .Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);

            }));
        }

    }
}
GMDev
  • 97
  • 1
  • 13
  • Please refer to https://briantjackett.com/2019/12/12/creating-a-c-azure-function-to-call-microsoft-graph/ – Jim Xu Jul 31 '20 at 06:58
  • Thanks for the link. But it seems like it is not up to date as he says that the significantly improved version of this class will be provided by Graph SDK team. I am not sure if they already provide the implementation or they mean Microsoft.Graph.Auth package by it, which will remain in Preview. – GMDev Jul 31 '20 at 08:36
  • Yes, you can use Microsoft.Identity namespace to implement it. Please refer to this [Stackoverflow thread](https://stackoverflow.com/questions/56152979/using-authprovider-with-ms-sdk-for-graph-calls-in-c-sharp). It would be better not to use preview in production because the preview features may change anytime and your application may break. Please go through [Preview Supplemental Terms](https://azure.microsoft.com/en-in/support/legal/preview-supplemental-terms/) – Shiva Keshav Varma Aug 18 '20 at 15:58

1 Answers1

0

I using the class UsernamePasswordCredential to create an credential to interact with the graph api.

var userNamePasswordCredential = new UsernamePasswordCredential(
            userName, password, tenantId, clientId, options);

var graphClient = new GraphServiceClient(userNamePasswordCredential, scopes);

Keep in mind: You can use a single client instance for the lifetime of the application. Create a Microsoft Graph client

Changer
  • 85
  • 1
  • 7