azureoffice365sharepoint-onlineoffice365-appsoffice-dev-pnp

How to authenticate our .NET console application against SharePoint online if we have `DisableCustomAppAuthentication` set to true


We have the following:-

now previously on old tenants i authenticate my code using this method by passing the ClientID and Client Secret:-

      static void Main(string[] args)
              {
                       
                  string siteUrl = "https://***.sharepoint.com/sites/CustomerServiceKB/";
                  string clientId = "******";
                  string clientSecret = "*****";
                  using (ClientContext context = new OfficeDevPnP.Core.AuthenticationManager().GetAppOnlyAuthenticatedContext(siteUrl, clientId, clientSecret))
            
                  {

but on our newly created tenant we can not authenticate our code using the above method, because we have the DisableCustomAppAuthentication set to true.. now we do not want to modify this property.

So our question is; if we have the DisableCustomAppAuthentication set to true (ans we do not want to set it to false), then how we can authenticate our console application? which is hosted inside our windows server and which runs on schedule basis using tasks scheduler ?


Solution

  • So the DisableCustomAppAuthentication property was brought in (and was set to true by default) to support the deprecation of the Azure Access Control Service (ACS). The modern way to authenticate custom apps in Sharepoint tenants is to register them in the Azure AD.

    Before moving on, consider the pros and cons of switching to the new authentication scheme. Mainly, the ACS enables users to granularly control site-level permissions for the application authentication, but Azure AD app registration makes the set of running applications transparent to the administrators. If you want to stay with ACS, just set the DisableCustomAppAuthentication to false.

    Now, if you decided to move on with registering the application in the Azure ID, here are the steps to follow:

    1. Log in to the Azure portal and navigate to the Azure Active Directory.

    2. Register the application in the Azure AD portal. Here's a guide on how to do it. Obtain the application (client) ID on the application overview page.

    3. Set all the necessary permissions, confirm them as a global administrator (or ask the administrator for confirmation).

    4. Configure the authentication. Choose the authentication option: whether you want the application to authenticate itself in the Microsoft IAM via a cryptographic certificate or a client secret.

    5. Obtain your Azure Active Directory tenant ID (not to be confused with the Sharepoint Online tenant ID). Here's how to do in in the Azure AD; there's also a hacky way.

    6. Now use the client ID (from step 2), the authentication option (step 4), and the AAD tenant ID (step 5) to authenticate and run your application:

        using Microsoft.Identity.Client;
      
        [..]
      
        private static async Task<string> GetToken()
        {
            string applicationId = "client-id";
            string tenantId = "aad-tenant-id";
            bool isUsingClientSecret = <true or false>;
      
            IConfidentialClientApplication app;
      
            if (isUsingClientSecret)
            {
                string secret = "secret";
                app = ConfidentialClientApplicationBuilder.Create(applicationId)
                    .WithClientSecret(secret)
                    .WithAuthority($"https://login.microsoftonline.com/{tenantId}")
                    .Build();
            }
      
            else
            {
                string certificateLocation = "certificate-file";
                X509Certificate2 certificate = ReadCertificate(certificateLocation);
                app = ConfidentialClientApplicationBuilder.Create(applicationId)
                    .WithCertificate(certificate)
                    .WithAuthority($"https://login.microsoftonline.com/{tenantId}")
                    .Build();
            }
      
            var scopes = new[] { "https://***.sharepoint.com/.default" };
            var authenticationResult = await app.AcquireTokenForClient(scopes).ExecuteAsync();
            return authenticationResult.AccessToken;
        }
      
        static async Task MainAsync(string[] args)
        {
            string site = "https://***.sharepoint.com/sites/CustomerServiceKB";
            string token = await GetToken();
            using (ClientContext context = new ClientContext(site))
            {
                context.ExecutingWebRequest += (s, e) =>
                {
                    e.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + token;
                };
                Web web = context.Web;
                context.Load(web);
                context.ExecuteQuery();
            }
        }
      
        static void Main(string[] args)
        {
            try
            {
                AsyncContext.Run(() => MainAsync(args));
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex);
                throw;
            }
        }