using Aip.Service.Aip.Models; using Microsoft.Identity.Client; using Microsoft.Identity.Client.Extensions.Msal; using Microsoft.InformationProtection; using System.Reflection; namespace Aip.Service.Aip; public class AuthDelegateImplementation : IAuthDelegate { private readonly Serilog.ILogger _log; public int LastErrNo { get; set; } public string LastErrMsg { get; set; } private readonly AipConfig _aipConfig; private readonly IConfidentialClientApplication _confidentialApp; // [Obsolete("Obsolete")] private TokenCache _tokenCache = new TokenCache(); public AuthDelegateImplementation(Serilog.Core.Logger logger, AipConfig aipConfig) { _log = logger.ForContext(); _aipConfig = aipConfig; LastErrNo = 0; LastErrMsg = string.Empty; var storageProperties = new StorageCreationPropertiesBuilder( "AIPGateway.Cache", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)) .Build(); var cacheHelper = MsalCacheHelper.CreateAsync(storageProperties).GetAwaiter().GetResult(); ConfidentialClientApplicationOptions options = new ConfidentialClientApplicationOptions() { ClientSecret = _aipConfig.SecretValue, ClientId = _aipConfig.ClientId, TenantId = _aipConfig.TenantId, RedirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient", Instance = "https://login.microsoftonline.com/" }; _confidentialApp = ConfidentialClientApplicationBuilder .CreateWithApplicationOptions(options) .WithRedirectUri(options.RedirectUri) // .WithLegacyCacheCompatibility(false) // .WithExperimentalFeatures() // for PoP // .WithCacheOptions(CacheOptions.EnableSharedCacheOptions) .Build(); cacheHelper.RegisterCache(_confidentialApp.UserTokenCache); } public void ResetError() { LastErrNo = 0; LastErrMsg = string.Empty; } private void SetError(int errNo, string errMsg1, string errMsg2 = "No Exception Message.") { LastErrNo = errNo; LastErrMsg = errMsg1 + "\r\n" + errMsg2; _log.Error("AuthDelegateImplementation::SetError ==> {0}, {1}, {2}", errNo, errMsg1, errMsg2); } public string AcquireToken(Identity identity, string authority, string resource, string claim) { return AcquireTokenByCertificate(identity, authority, resource, claim); } private string AcquireTokenByCertificate(Identity identity, string authority, string resource, string claims) { var scopes = new[] { resource[resource.Length - 1].Equals('/') ? $"{resource}.default" : $"{resource}/.default" }; try { AuthenticationResult result; result = _confidentialApp.AcquireTokenForClient(scopes) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false) .GetAwaiter() .GetResult(); return result.AccessToken; } catch (MsalUiRequiredException ex) when (ex.Message.Contains("AADSTS70011")) { SetError(1, "AcquireTokenByCertificate::AcquireTokenByCertificate, Scope provided is not supported.", ex.Message); } catch (Exception ex) { SetError(1, "AcquireTokenByCertificate::AcquireTokenByCertificate Failed.", ex.Message); } return ""; } }