/// <summary> /// Checks if the sample is configured for using ClientSecret or Certificate. This method is just for the sake of this sample. /// You won't need this verification in your production application since you will be authenticating in AAD using one mechanism only. /// </summary> /// <param name="config">Configuration from appsettings.json</param> /// <returns></returns> private static bool AppUsesClientSecret(AuthenticationConfig config) { string clientSecretPlaceholderValue = "ClientSecret"; string certificatePlaceholderValue = "[Or instead of client secret: Enter here the name of a certificate (from the user cert store) as registered with your application]"; if (!String.IsNullOrWhiteSpace(config.ClientSecret) && config.ClientSecret != clientSecretPlaceholderValue) { return(true); } else if (!String.IsNullOrWhiteSpace(config.CertificateName) && config.CertificateName != certificatePlaceholderValue) { return(false); } else { throw new Exception("You must choose between using client secret or certificate. Please update appsettings.json file."); } }
private static async Task RunAsync() { AuthenticationConfig config = AuthenticationConfig.ReadFromJsonFile("appsettings.json"); // You can run this sample using ClientSecret or Certificate. The code will differ only when instantiating the IConfidentialClientApplication bool isUsingClientSecret = AppUsesClientSecret(config); // Even if this is a console application here, a daemon application is a confidential client application IConfidentialClientApplication app; if (isUsingClientSecret) { app = ConfidentialClientApplicationBuilder.Create(config.ClientId) .WithClientSecret(config.ClientSecret) .WithAuthority(new Uri(config.Authority)) .Build(); } else { X509Certificate2 certificate = ReadCertificate(config.CertificateName); app = ConfidentialClientApplicationBuilder.Create(config.ClientId) .WithCertificate(certificate) .WithAuthority(new Uri(config.Authority)) .Build(); } // With client credentials flows the scopes is ALWAYS of the shape "resource/.default", as the // application permissions need to be set statically (in the portal or by PowerShell), and then granted by // a tenant administrator string[] scopes = new string[] { config.TargetApiScope }; AuthenticationResult result = null; try { result = await app.AcquireTokenForClient(scopes) .ExecuteAsync(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Token acquired \n"); Console.ResetColor(); } catch (MsalServiceException ex) when(ex.Message.Contains("AADSTS70011")) { // Invalid scope. The scope has to be of the form "https://resourceurl/.default" // Mitigation: change the scope to be as expected Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Scope provided is not supported"); Console.ResetColor(); } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(ex); Console.ResetColor(); } if (result != null) { var httpClient = new HttpClient(); var apiCaller = new ProtectedApiCallHelper(httpClient); await apiCaller.CallWebApiAndProcessResultASync($"{config.TargetApiBaseAddress}/WeatherForecast/GetDataByRole", result.AccessToken, Display); } }