123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- using System;
- using System.Linq;
- using System.Security.Cryptography.X509Certificates;
- using System.Threading.Tasks;
- using Microsoft.Identity.Client;
- using Microsoft.InformationProtection;
- namespace AipGateway.AIP
- {
- public class AuthDelegateImplementation : IAuthDelegate
- {
- public int LastErrNo { get; set; }
- public string LastErrMsg { get; set; }
- private readonly AipConfig _aipConfig;
- public AuthDelegateImplementation(AipConfig aipConfig)
- {
- _aipConfig = aipConfig;
- LastErrNo = 0;
- LastErrMsg = String.Empty;
- }
- 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;
- Console.WriteLine("AuthDelegateImplementation::SetError ==> {0}, {1}, {2}", errNo, errMsg1, errMsg2);
- }
- public string AcquireToken(Identity identity, string authority, string resource, string claim)
- {
- Console.WriteLine("AuthDelegateImplementation::AcquireToken ==> LoginType: {0}", _aipConfig.LoginType);
- if (_aipConfig.LoginType == AipAuthLoginType.authLoginPassword)
- {
- return AcquireTokenByPassword(identity, authority, resource, claim);
- }
-
- if (_aipConfig.LoginType == AipAuthLoginType.authLoginCert)
- {
- return AcquireTokenByCert(identity, authority, resource, claim);
- }
- return AcquireTokenById(identity, authority, resource, claim);
- }
- private string AcquireTokenByPassword(Identity identity, string authority, string resource, string claims)
- {
- Console.WriteLine("AuthDelegateImplementation::AcquireTokenByPassword");
- AuthenticationResult result;
- var authorityUri = new Uri(authority);
- authority = $"https://{authorityUri.Host}/{_aipConfig.TenantId}";
-
- var app = ConfidentialClientApplicationBuilder.Create(_aipConfig.ClientId)
- .WithClientSecret(_aipConfig.SecretValue)
- .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
- .Build();
- var scopes = new[] { resource[resource.Length - 1].Equals('/') ? $"{resource}.default" : $"{resource}/.default" };
- //app.AddInMemoryTokenCache();
- try
- {
- result = app.AcquireTokenForClient(scopes)
- .WithTenantId(_aipConfig.TenantId)
- .ExecuteAsync()
- .GetAwaiter()
- .GetResult();
- }
- 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
- SetError(1, "AcquireTokenByPassword.Scope provided is not supported.", ex.Message);
- return null;
- }
- return result.AccessToken;
- }
- private string AcquireTokenByCert(Identity identity, string authority, string resource, string claims)
- {
- Console.WriteLine("AuthDelegateImplementation::AcquireTokenByPassword");
- AuthenticationResult result;
- var authorityUri = new Uri(authority);
- authority = $"https://{authorityUri.Host}/{_aipConfig.TenantId}";
- // Read cert from local machine
- //var certificate = ReadCertificateFromStore(certThumb);
- var myCertificate = X509Certificate2.CreateFromCertFile(_aipConfig.CertThumbPrint);
- X509Certificate2 certificate = new X509Certificate2(myCertificate);
- // Use cert to build ClientAssertionCertificate
- var app = ConfidentialClientApplicationBuilder.Create(_aipConfig.ClientId)
- .WithCertificate(certificate)
- .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
- .Build();
- // Append .default to the resource passed in to AcquireToken().
- var scopes = new[] { resource[resource.Length - 1].Equals('/') ? $"{resource}.default" : $"{resource}/.default" };
- try
- {
- result = app.AcquireTokenForClient(scopes).ExecuteAsync().Result;
- }
- 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
- SetError(1, "AcquireTokenByCert.Scope provided is not supported.", ex.Message);
- return null;
- }
- return result.AccessToken;
- }
- private string AcquireTokenById(Identity identity, string authority, string resource, string claims)
- {
- Console.WriteLine("AcquireTokenById::AcquireTokenByPassword");
- AuthenticationResult result;
- var authorityUri = new Uri(authority);
- authority = $"https://{authorityUri.Host}/{_aipConfig.TenantId}";
- var app = PublicClientApplicationBuilder.Create(_aipConfig.ClientId)
- .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
- .WithAuthority(AzureCloudInstance.AzurePublic, "2e58414a-c6ae-43ff-aaf5-45ab8b78a404")
- .Build();
- var accounts = (app.GetAccountsAsync()).GetAwaiter().GetResult();
- // Append .default to the resource passed in to AcquireToken().
- var scopes = new[] { resource[resource.Length - 1].Equals('/') ? $"{resource}.default" : $"{resource}/.default" };
- try
- {
- result = app.AcquireTokenInteractive(scopes)
- .WithAccount(accounts.FirstOrDefault())
- .WithPrompt(Prompt.SelectAccount)
- .ExecuteAsync()
- .ConfigureAwait(false)
- .GetAwaiter()
- .GetResult();
- }
- catch (Exception ex)
- {
- SetError(1, "AcquireTokenById.Login Failed.", ex.Message);
- return null;
- }
- return result.AccessToken;
- }
- private static X509Certificate2 ReadCertificateFromStore(string thumbprint)
- {
- X509Certificate2 cert = null;
- X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
- store.Open(OpenFlags.ReadOnly);
- X509Certificate2Collection certCollection = store.Certificates;
- // Find unexpired certificates.
- X509Certificate2Collection currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
- // From the collection of unexpired certificates, find the ones with the correct name.
- X509Certificate2Collection signingCert = currentCerts.Find(X509FindType.FindByThumbprint, thumbprint, false);
- // Return the first certificate in the collection, has the right name and is current.
- cert = signingCert.OfType<X509Certificate2>().OrderByDescending(c => c.NotBefore).FirstOrDefault();
- store.Close();
- return cert;
- }
- public async Task<AuthenticationResult> AcquireTokenAsync(string authority, string resource, string claims)
- {
- AuthenticationResult result = null;
- if (authority.ToLower().Contains("common"))
- {
- var authorityUri = new Uri(authority);
- authority = String.Format("https://{0}/{1}", authorityUri.Host, _aipConfig.TenantId);
- }
-
- var app = PublicClientApplicationBuilder.Create(_aipConfig.ClientId)
- .WithAuthority(authority)
- .WithDefaultRedirectUri()
- .Build();
- var accounts = (app.GetAccountsAsync()).GetAwaiter().GetResult();
- // Append .default to the resource passed in to AcquireToken().
- string[] scopes = { resource[resource.Length - 1].Equals('/') ? $"{resource}.default" : $"{resource}/.default" };
- try
- {
- result = await app.AcquireTokenSilent(new[] { "https://aadrm.com/user_impersonation" }, accounts.FirstOrDefault()).ExecuteAsync();
- // result = await _app.AcquireTokenSilent(scopes,
- // accounts.FirstOrDefault())
- // .ExecuteAsync();
- }
- catch (MsalUiRequiredException)
- {
- result = app.AcquireTokenInteractive(scopes)
- .WithAccount(accounts.FirstOrDefault())
- .WithPrompt(Prompt.SelectAccount)
- .ExecuteAsync()
- .ConfigureAwait(false)
- .GetAwaiter()
- .GetResult();
- }
- // Return the token. The token is sent to the resource.
- return result;
- }
- // private async Task<string> GetAccessTokenOnBehalfOfUser(string authority, string resource)
- // {
- // IConfidentialClientApplication app;
- //
- // if (false)
- // {
- // // Read X509 cert from local store and build ClientAssertionCertificate.
- // X509Certificate2 cert = Utilities.ReadCertificateFromStore(_aipConfig.CertThumbPrint);
- //
- // // Create confidential client using certificate.
- // app = ConfidentialClientApplicationBuilder.Create(_aipConfig.ClientId)
- // .WithRedirectUri(resource)
- // .WithAuthority(authority)
- // .WithCertificate(cert)
- // .Build();
- // }
- //
- // else
- // {
- // // Create confidential client using client secret.
- // app = ConfidentialClientApplicationBuilder.Create(_aipConfig.ClientId)
- // .WithRedirectUri(resource)
- // .WithAuthority(authority)
- // .WithClientSecret(_aipConfig.SecretValue)
- // .Build();
- // }
- //
- // // Store user access token of authenticated user.
- // var ci = (ClaimsIdentity)_claimsPrincipal.Identity;
- // string userAccessToken = (string)ci.BootstrapContext;
- //
- //
- // // Generate a user assertion with the UPN and access token.
- // UserAssertion userAssertion = new UserAssertion(userAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer");
- //
- // // Append .default to the resource passed in to AcquireToken().
- // List<string> scopes = new List<string>() { resource[resource.Length - 1].Equals('/') ? $"{resource}.default" : $"{resource}/.default" };
- //
- // AuthenticationResult result = await app.AcquireTokenOnBehalfOf(scopes, userAssertion)
- // .ExecuteAsync();
- //
- // // Return the token to the API caller
- // return (result.AccessToken);
- // }
- }
- }
|