public async Task AuthenticateWithDeviceCodeMockAsync2() { var expectedCode = Guid.NewGuid().ToString(); var expectedToken = Guid.NewGuid().ToString(); var mockTransport = new MockTransport(request => ProcessMockRequest(request, expectedCode, expectedToken)); var options = new TokenCredentialOptions() { Transport = mockTransport }; var cred = InstrumentClient(new DeviceCodeCredential((code, cancelToken) => VerifyDeviceCode(code, expectedCode), ClientId, options: options)); AccessToken token = await cred.GetTokenAsync(new TokenRequestContext(new string[] { "https://vault.azure.net/.default" })); Assert.AreEqual(token.Token, expectedToken); }
public async Task AuthenticateWithAuthCodeHonorsTenantId([Values(null, TenantIdHint)] string tenantId, [Values(true)] bool allowMultiTenantAuthentication) { options = new TokenCredentialOptions { AllowMultiTenantAuthentication = allowMultiTenantAuthentication }; var context = new TokenRequestContext(new[] { Scope }, tenantId: tenantId); expectedTenantId = TenantIdResolver.Resolve(TenantId, context, options.AllowMultiTenantAuthentication); AuthorizationCodeCredential cred = InstrumentClient(new AuthorizationCodeCredential(TenantId, ClientId, clientSecret, authCode, options, mockMsalClient)); AccessToken token = await cred.GetTokenAsync(context); Assert.AreEqual(token.Token, expectedToken, "Should be the expected token value"); AccessToken token2 = await cred.GetTokenAsync(context); Assert.AreEqual(token2.Token, expectedToken, "Should be the expected token value"); }
public override TokenCredential GetTokenCredential(TokenCredentialOptions options) { using var env = new TestEnvVar(new Dictionary <string, string> { { "TENANT_ID", TenantId } }); var environment = new IdentityTestEnvironment(); var vscOptions = new VisualStudioCodeCredentialOptions { Diagnostics = { IsAccountIdentifierLoggingEnabled = options.Diagnostics.IsAccountIdentifierLoggingEnabled }, TenantId = environment.TenantId, Transport = new MockTransport() }; return(InstrumentClient( new VisualStudioCodeCredential( vscOptions, null, mockPublicMsalClient, CredentialTestHelpers.CreateFileSystemForVisualStudioCode(environment), new TestVscAdapter("VS Code Azure", "AzureCloud", expectedToken)))); }
public async Task AuthenticateWithDeviceCodeMockAsync([Values(null, TenantIdHint)] string tenantId, [Values(true)] bool allowMultiTenantAuthentication) { options = new TokenCredentialOptions { AllowMultiTenantAuthentication = allowMultiTenantAuthentication }; var context = new TokenRequestContext(new[] { Scope }, tenantId: tenantId); expectedTenantId = TenantIdResolver.Resolve(TenantId, context, options.AllowMultiTenantAuthentication); var cred = InstrumentClient( new DeviceCodeCredential((code, _) => VerifyDeviceCode(code, expectedCode), TenantId, ClientId, options, null, mockMsalClient)); AccessToken token = await cred.GetTokenAsync(context); Assert.AreEqual(token.Token, expectedToken); token = await cred.GetTokenAsync(context); Assert.AreEqual(token.Token, expectedToken); }
public async Task AuthenticateWithDeviceCodeMockVerifyMsalCancellationAsync() { var cancelSource = new CancellationTokenSource(); var options = new TokenCredentialOptions(); var cred = InstrumentClient( new DeviceCodeCredential( (code, cancelToken) => VerifyDeviceCodeAndCancel(code, expectedCode, cancelSource), null, ClientId, options, null, mockPublicMsalClient)); var ex = Assert.CatchAsync <OperationCanceledException>( async() => await cred.GetTokenAsync(new TokenRequestContext(new[] { Scope }), cancelSource.Token)); await Task.CompletedTask; }
public void AuthenticateWithDeviceCodeCallbackThrowsAsync() { var expectedCode = Guid.NewGuid().ToString(); var expectedToken = Guid.NewGuid().ToString(); var cancelSource = new CancellationTokenSource(); var mockTransport = new MockTransport(request => ProcessMockRequest(request, expectedCode, expectedToken)); var options = new TokenCredentialOptions() { Transport = mockTransport }; var cred = InstrumentClient(new DeviceCodeCredential(ThrowingDeviceCodeCallback, ClientId, options: options)); Assert.ThrowsAsync <MockException>(async() => await cred.GetTokenAsync(new TokenRequestContext(new string[] { "https://vault.azure.net/.default" }), cancelSource.Token)); }
public async Task VerifyImdsRequestMockAsync() { using (new TestEnvVar("MSI_ENDPOINT", null)) using (new TestEnvVar("MSI_SECRET", null)) { var response = new MockResponse(200); var expectedToken = "mock-msi-access-token"; response.SetContent($"{{ \"access_token\": \"{expectedToken}\", \"expires_on\": \"3600\" }}"); var mockTransport = new MockTransport(response); var options = new TokenCredentialOptions() { Transport = mockTransport }; var pipeline = CredentialPipeline.GetInstance(options); ManagedIdentityCredential credential = InstrumentClient(new ManagedIdentityCredential(pipeline, new MockManagedIdentityClient(pipeline, "mock-client-id") { ImdsAvailableFunc = _ => true })); AccessToken actualToken = await credential.GetTokenAsync(new TokenRequestContext(MockScopes.Default)); Assert.AreEqual(expectedToken, actualToken.Token); MockRequest request = mockTransport.Requests[0]; string query = request.Uri.Query; Assert.IsTrue(query.Contains("api-version=2018-02-01")); Assert.IsTrue(query.Contains($"resource={Uri.EscapeDataString(ScopeUtilities.ScopesToResource(MockScopes.Default))}")); Assert.IsTrue(request.Headers.TryGetValue("Metadata", out string metadataValue)); Assert.AreEqual("true", metadataValue); } }
public async Task VerifyClientSecretRequestFailedAsync() { var response = new MockResponse(400); response.SetContent($"{{ \"error_code\": \"InvalidSecret\", \"message\": \"The specified client_secret is incorrect\" }}"); var mockTransport = new MockTransport(response); var options = new TokenCredentialOptions() { Transport = mockTransport }; var expectedTenantId = Guid.NewGuid().ToString(); var expectedClientId = Guid.NewGuid().ToString(); var expectedClientSecret = "secret"; ClientSecretCredential client = InstrumentClient(new ClientSecretCredential(expectedTenantId, expectedClientId, expectedClientSecret, options)); Assert.ThrowsAsync <AuthenticationFailedException>(async() => await client.GetTokenAsync(new TokenRequestContext(MockScopes.Default))); await Task.CompletedTask; }
public async Task VerifyAppServiceMsiRequestWithClientIdMockAsync() { using (new TestEnvVar("MSI_ENDPOINT", "https://mock.msi.endpoint/")) using (new TestEnvVar("MSI_SECRET", "mock-msi-secret")) { var response = new MockResponse(200); var expectedToken = "mock-msi-access-token"; response.SetContent($"{{ \"access_token\": \"{expectedToken}\", \"expires_on\": \"{DateTimeOffset.UtcNow.ToString()}\" }}"); var mockTransport = new MockTransport(response); var options = new TokenCredentialOptions() { Transport = mockTransport }; ManagedIdentityCredential credential = InstrumentClient(new ManagedIdentityCredential("mock-client-id", options)); AccessToken actualToken = await credential.GetTokenAsync(new TokenRequestContext(MockScopes.Default)); Assert.AreEqual(expectedToken, actualToken.Token); MockRequest request = mockTransport.SingleRequest; Assert.IsTrue(request.Uri.ToString().StartsWith("https://mock.msi.endpoint/")); string query = request.Uri.Query; Assert.IsTrue(query.Contains("api-version=2017-09-01")); Assert.IsTrue(query.Contains($"resource={Uri.EscapeDataString(ScopeUtilities.ScopesToResource(MockScopes.Default))}")); Assert.IsTrue(query.Contains($"clientid=mock-client-id")); Assert.IsTrue(request.Headers.TryGetValue("secret", out string actSecretValue)); Assert.AreEqual("mock-msi-secret", actSecretValue); } }
public void VerifyImdsAvailableUserCanceledMockAsync() { using (new TestEnvVar("MSI_ENDPOINT", null)) using (new TestEnvVar("MSI_SECRET", null)) { var mockTransport = new MockTransport(request => throw new OperationCanceledException("mock user canceled exception")); var options = new TokenCredentialOptions() { Transport = mockTransport }; ManagedIdentityCredential credential = InstrumentClient(new ManagedIdentityCredential("mock-client-id", options)); CancellationTokenSource cancellationSource = new CancellationTokenSource(); cancellationSource.Cancel(); Assert.CatchAsync <OperationCanceledException>(async() => await credential.GetTokenAsync(new TokenRequestContext(MockScopes.Default), cancellationSource.Token)); } }
public async Task AuthenticateWithDeviceCodeMockVerifyMsalCancellationAsync() { var expectedCode = Guid.NewGuid().ToString(); var expectedToken = Guid.NewGuid().ToString(); var cancelSource = new CancellationTokenSource(); var mockTransport = new MockTransport(request => ProcessMockRequest(request, expectedCode, expectedToken)); var options = new TokenCredentialOptions() { Transport = mockTransport }; var cred = InstrumentClient(new DeviceCodeCredential((code, cancelToken) => VerifyDeviceCodeAndCancel(code, expectedCode, cancelSource), null, ClientId, options: options)); var ex = Assert.CatchAsync <OperationCanceledException>(async() => await cred.GetTokenAsync(new TokenRequestContext(new string[] { "https://vault.azure.net/.default" }), cancelSource.Token)); await Task.CompletedTask; }
public async Task VerifyImdsRequestWithClientIdMockAsync() { using (new TestEnvVar("MSI_ENDPOINT", null)) using (new TestEnvVar("MSI_SECRET", null)) { var response = new MockResponse(200); var expectedToken = "mock-msi-access-token"; response.SetContent($"{{ \"access_token\": \"{expectedToken}\", \"expires_on\": \"3600\" }}"); var mockTransport = new MockTransport(response, response); var options = new TokenCredentialOptions() { Transport = mockTransport }; ManagedIdentityClient client = InstrumentClient(new ManagedIdentityClient(options)); AccessToken actualToken = await client.AuthenticateAsync(MockScopes.Default, clientId : "mock-client-id"); Assert.AreEqual(expectedToken, actualToken.Token); MockRequest request = mockTransport.Requests[mockTransport.Requests.Count - 1]; string query = request.Uri.Query; Assert.IsTrue(query.Contains("api-version=2018-02-01")); Assert.IsTrue(query.Contains($"resource={Uri.EscapeDataString(ScopeUtilities.ScopesToResource(MockScopes.Default))}")); Assert.IsTrue(query.Contains($"client_id=mock-client-id")); Assert.IsTrue(request.Headers.TryGetValue("Metadata", out string metadataValue)); Assert.AreEqual("true", metadataValue); } }
public void AuthenticateWithDeviceCodeCallbackThrowsAsync() { IdentityTestEnvironment testEnvironment = new IdentityTestEnvironment(); var expectedCode = Guid.NewGuid().ToString(); var expectedToken = Guid.NewGuid().ToString(); var cancelSource = new CancellationTokenSource(); var mockTransport = new MockTransport(request => ProcessMockRequest(request, expectedCode, expectedToken)); var options = new TokenCredentialOptions() { Transport = mockTransport }; var cred = InstrumentClient(new DeviceCodeCredential(ThrowingDeviceCodeCallback, ClientId, options: options)); var ex = Assert.ThrowsAsync <AuthenticationFailedException>(async() => await cred.GetTokenAsync(new TokenRequestContext(new string[] { testEnvironment.KeyvaultScope }), cancelSource.Token)); Assert.IsInstanceOf(typeof(MockException), ex.InnerException); }
public abstract TokenCredential GetTokenCredential(TokenCredentialOptions options);
public async Task <string> GetData(string configuration, string name) { var configurationObj = JsonSerializerHelper.Deserialize <Configuration>(configuration); var credentialOption = new TokenCredentialOptions(); credentialOption.AuthorityHost = new Uri(configurationObj.AzureLoginUri); TokenCredential credential; switch (configurationObj.Type) { case 1: //ClientSecret credential = new ClientSecretCredential(configurationObj.TenantId, configurationObj.ClientId, configurationObj.ClientSecret, credentialOption); break; case 2: //UsernamePassword credential = new UsernamePasswordCredential(configurationObj.UserName, configurationObj.Password, configurationObj.TenantId, configurationObj.ClientId, credentialOption); break; case 3: //ManagedIdentity string clientID = null; if (!string.IsNullOrEmpty(configurationObj.ClientId)) { clientID = configurationObj.ClientId; } credential = new ManagedIdentityCredential(clientID); break; default: var fragment = new TextFragment() { Code = TextCodes.NotSupportAzureVaultAuthType, DefaultFormatting = "不支持方式为{0}的AzureVault验证方式,发生位置为{1}", ReplaceParameters = new List <object>() { configurationObj.Type.ToString(), $"{this.GetType().FullName}.GetData" } }; throw new UtilityException((int)Errors.NotSupportAzureVaultAuthType, fragment); } SecretClientOptions options = new SecretClientOptions() { Retry = { Delay = TimeSpan.FromSeconds(2), MaxDelay = TimeSpan.FromSeconds(16), MaxRetries = 5, Mode = RetryMode.Exponential } }; var client = new SecretClient(new Uri($"https://{configurationObj.VaultName}{configurationObj.VaultUriSuffix}"), credential, options); var result = await client.GetSecretAsync(name); return(result.Value.Value); }
/// <summary> /// Creates an instance of the ClientSecretCredential with the details needed to authenticate against Azure Active Directory with a client secret. /// </summary> /// <param name="tenantId">The Azure Active Directory tenant (directory) Id of the service principal.</param> /// <param name="clientId">The client (application) ID of the service principal</param> /// <param name="clientSecret">A client secret that was generated for the App Registration used to authenticate the client.</param> /// <param name="options">Options that allow to configure the management of the requests sent to the Azure Active Directory service.</param> public ClientAssertionCredential(string tenantId, string clientId, string clientSecret, TokenCredentialOptions options) : this(tenantId, clientId, clientSecret, options, null, null) { }
internal static TokenCredential CreateCredential(IConfiguration configuration, TokenCredentialOptions identityClientOptions = null) { var credentialType = configuration["credential"]; var clientId = configuration["clientId"]; var tenantId = configuration["tenantId"]; var clientSecret = configuration["clientSecret"]; var certificate = configuration["clientCertificate"]; var certificateStoreName = configuration["clientCertificateStoreName"]; var certificateStoreLocation = configuration["clientCertificateStoreLocation"]; if (string.Equals(credentialType, "managedidentity", StringComparison.OrdinalIgnoreCase)) { return(new ManagedIdentityCredential(clientId)); } if (!string.IsNullOrWhiteSpace(tenantId) && !string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(clientSecret)) { return(new ClientSecretCredential(tenantId, clientId, clientSecret, identityClientOptions)); } if (!string.IsNullOrWhiteSpace(tenantId) && !string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(certificate)) { StoreLocation storeLocation = StoreLocation.CurrentUser; if (!string.IsNullOrWhiteSpace(certificateStoreLocation)) { storeLocation = (StoreLocation)Enum.Parse(typeof(StoreLocation), certificateStoreLocation, true); } if (string.IsNullOrWhiteSpace(certificateStoreName)) { certificateStoreName = "MY"; // MY is the default used in X509Store } using var store = new X509Store(certificateStoreName, storeLocation); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByThumbprint, certificate, false); if (certs.Count == 0) { throw new InvalidOperationException($"Unable to find a certificate with thumbprint '{certificate}'"); } var credential = new ClientCertificateCredential(tenantId, clientId, certs[0], identityClientOptions); store.Close(); return(credential); } // TODO: More logging return(null); }
private ManagedIdentityCredential CreateManagedIdentityCredential(string clientId = null, TokenCredentialOptions options = null) { options = Recording.InstrumentClientOptions(options ?? new TokenCredentialOptions()); var pipeline = CredentialPipeline.GetInstance(options); // if we're in playback mode we need to mock the ImdsAvailable call since we won't be able to open a connection var client = (Mode == RecordedTestMode.Playback) ? new MockManagedIdentityClient(pipeline, clientId) { ImdsAvailableFunc = _ => true } : new ManagedIdentityClient(pipeline, clientId); var cred = new ManagedIdentityCredential(pipeline, client); return(cred); }
public MockMsalClient(CredentialPipeline pipeline, string tenantId, string clientId, TokenCredentialOptions options) : base(pipeline, tenantId, clientId, options) { }
internal ClientAssertionCredential(string tenantId, string clientId, string clientSecret, TokenCredentialOptions options, CredentialPipeline pipeline, MsalConfidentialClient client) { TenantId = Validations.ValidateTenantId(tenantId, nameof(tenantId)); ClientId = clientId ?? throw new ArgumentNullException(nameof(clientId)); ClientSecret = clientSecret ?? throw new ArgumentNullException(nameof(clientSecret)); _pipeline = pipeline ?? CredentialPipeline.GetInstance(options); _client = client ?? new MsalConfidentialClient(_pipeline, tenantId, clientId, clientSecret, options as ITokenCacheOptions); }
public void SetAuthorityHostToNonHttpsEndpointThrows() { TokenCredentialOptions options = new TokenCredentialOptions(); Assert.Throws <ArgumentException>(() => options.AuthorityHost = new Uri("http://unprotected.login.com")); }
protected async Task Initialize() { Location = AzureLocation.CanadaCentral; Client = GetArmClient(); Subscription = await Client.GetDefaultSubscriptionAsync(); DeletedVaultCollection = Subscription.GetDeletedVaults(); if (Mode == RecordedTestMode.Playback) { this.ObjectId = Recording.GetVariable(ObjectIdKey, string.Empty); } else if (Mode == RecordedTestMode.Record) { // Get ObjectId of Service Principal // [warning] Microsoft.Graph required corresponding api permission, Please make sure the service has these two api permissions as follows. // 1. ServicePrincipalEndpoint.Read.All(TYPE-Application) 2.ServicePrincipalEndpoint.ReadWrite.All(TYPE-Application) var scopes = new[] { "https://graph.microsoft.com/.default" }; var options = new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud }; var clientSecretCredential = new ClientSecretCredential(TestEnvironment.TenantId, TestEnvironment.ClientId, TestEnvironment.ClientSecret, options); var graphClient = new GraphServiceClient(clientSecretCredential, scopes); var response = await graphClient.ServicePrincipals.Request().GetAsync(); var result = response.CurrentPage.Where(i => i.AppId == TestEnvironment.ClientId).FirstOrDefault(); this.ObjectId = result.Id; Recording.GetVariable(ObjectIdKey, this.ObjectId); } ResGroupName = Recording.GenerateAssetName("sdktestrg-kv-"); ArmOperation <ResourceGroupResource> rgResponse = await Subscription.GetResourceGroups().CreateOrUpdateAsync(WaitUntil.Completed, ResGroupName, new ResourceGroupData(Location)).ConfigureAwait(false); ResourceGroupResource = rgResponse.Value; VaultCollection = ResourceGroupResource.GetVaults(); VaultName = Recording.GenerateAssetName("sdktest-vault-"); MHSMName = Recording.GenerateAssetName("sdktest-mhsm-"); TenantIdGuid = new Guid(TestEnvironment.TenantId); Tags = new Dictionary <string, string> { { "tag1", "value1" }, { "tag2", "value2" }, { "tag3", "value3" } }; IdentityAccessPermissions permissions = new IdentityAccessPermissions { Keys = { new KeyPermission("all") }, Secrets = { new SecretPermission("all") }, Certificates = { new CertificatePermission("all") }, Storage = { new StoragePermission("all") }, }; AccessPolicy = new VaultAccessPolicy(TenantIdGuid, ObjectId, permissions); VaultProperties = new VaultProperties(TenantIdGuid, new KeyVaultSku(KeyVaultSkuFamily.A, KeyVaultSkuName.Standard)); VaultProperties.EnabledForDeployment = true; VaultProperties.EnabledForDiskEncryption = true; VaultProperties.EnabledForTemplateDeployment = true; VaultProperties.EnableSoftDelete = true; VaultProperties.SoftDeleteRetentionInDays = DefSoftDeleteRetentionInDays; VaultProperties.VaultUri = new Uri("http://vaulturi.com"); VaultProperties.NetworkRuleSet = new VaultNetworkRuleSet() { Bypass = "******", DefaultAction = "Allow", IPRules = { new VaultIPRule("1.2.3.4/32"), new VaultIPRule("1.0.0.0/25") } }; VaultProperties.AccessPolicies.Add(AccessPolicy); ManagedHsmCollection = ResourceGroupResource.GetManagedHsms(); ManagedHsmProperties = new ManagedHsmProperties(); ManagedHsmProperties.InitialAdminObjectIds.Add(ObjectId); ManagedHsmProperties.CreateMode = ManagedHsmCreateMode.Default; ManagedHsmProperties.EnableSoftDelete = true; ManagedHsmProperties.SoftDeleteRetentionInDays = DefSoftDeleteRetentionInDays; ManagedHsmProperties.EnablePurgeProtection = false; ManagedHsmProperties.NetworkRuleSet = new ManagedHsmNetworkRuleSet() { Bypass = "******", DefaultAction = "Deny" //Property properties.networkAcls.ipRules is not supported currently and must be set to null. }; ManagedHsmProperties.PublicNetworkAccess = PublicNetworkAccess.Disabled; ManagedHsmProperties.TenantId = TenantIdGuid; }
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/AcquireTokenAsync/*'/> public override async Task <SqlAuthenticationToken> AcquireTokenAsync(SqlAuthenticationParameters parameters) { CancellationTokenSource cts = new CancellationTokenSource(); // Use Connection timeout value to cancel token acquire request after certain period of time. cts.CancelAfter(parameters.ConnectionTimeout * 1000); // Convert to milliseconds string scope = parameters.Resource.EndsWith(s_defaultScopeSuffix) ? parameters.Resource : parameters.Resource + s_defaultScopeSuffix; string[] scopes = new string[] { scope }; int seperatorIndex = parameters.Authority.LastIndexOf('/'); string tenantId = parameters.Authority.Substring(seperatorIndex + 1); string authority = parameters.Authority.Remove(seperatorIndex + 1); TokenRequestContext tokenRequestContext = new TokenRequestContext(scopes); string clientId = string.IsNullOrWhiteSpace(parameters.UserId) ? null : parameters.UserId; if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryDefault) { DefaultAzureCredentialOptions defaultAzureCredentialOptions = new DefaultAzureCredentialOptions() { AuthorityHost = new Uri(authority), ManagedIdentityClientId = clientId, InteractiveBrowserTenantId = tenantId, SharedTokenCacheTenantId = tenantId, SharedTokenCacheUsername = clientId, VisualStudioCodeTenantId = tenantId, VisualStudioTenantId = tenantId, ExcludeInteractiveBrowserCredential = true // Force disabled, even though it's disabled by default to respect driver specifications. }; AccessToken accessToken = await new DefaultAzureCredential(defaultAzureCredentialOptions).GetTokenAsync(tokenRequestContext, cts.Token); SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Default auth mode. Expiry Time: {0}", accessToken.ExpiresOn); return(new SqlAuthenticationToken(accessToken.Token, accessToken.ExpiresOn)); } TokenCredentialOptions tokenCredentialOptions = new TokenCredentialOptions() { AuthorityHost = new Uri(authority) }; if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryManagedIdentity || parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryMSI) { AccessToken accessToken = await new ManagedIdentityCredential(clientId, tokenCredentialOptions).GetTokenAsync(tokenRequestContext, cts.Token); SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Managed Identity auth mode. Expiry Time: {0}", accessToken.ExpiresOn); return(new SqlAuthenticationToken(accessToken.Token, accessToken.ExpiresOn)); } AuthenticationResult result; if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryServicePrincipal) { AccessToken accessToken = await new ClientSecretCredential(tenantId, parameters.UserId, parameters.Password, tokenCredentialOptions).GetTokenAsync(tokenRequestContext, cts.Token); SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Service Principal auth mode. Expiry Time: {0}", accessToken.ExpiresOn); return(new SqlAuthenticationToken(accessToken.Token, accessToken.ExpiresOn)); } /* * Today, MSAL.NET uses another redirect URI by default in desktop applications that run on Windows * (urn:ietf:wg:oauth:2.0:oob). In the future, we'll want to change this default, so we recommend * that you use https://login.microsoftonline.com/common/oauth2/nativeclient. * * https://docs.microsoft.com/en-us/azure/active-directory/develop/scenario-desktop-app-registration#redirect-uris */ string redirectUri = s_nativeClientRedirectUri; #if NETCOREAPP if (parameters.AuthenticationMethod != SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow) { redirectUri = "http://localhost"; } #endif PublicClientAppKey pcaKey = new PublicClientAppKey(parameters.Authority, redirectUri, _applicationClientId #if NETFRAMEWORK , _iWin32WindowFunc #endif #if NETSTANDARD , _parentActivityOrWindowFunc #endif ); IPublicClientApplication app = GetPublicClientAppInstance(pcaKey); if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryIntegrated) { if (!string.IsNullOrEmpty(parameters.UserId)) { result = await app.AcquireTokenByIntegratedWindowsAuth(scopes) .WithCorrelationId(parameters.ConnectionId) .WithUsername(parameters.UserId) .ExecuteAsync(cancellationToken: cts.Token); } else { result = await app.AcquireTokenByIntegratedWindowsAuth(scopes) .WithCorrelationId(parameters.ConnectionId) .ExecuteAsync(cancellationToken: cts.Token); } SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Integrated auth mode. Expiry Time: {0}", result?.ExpiresOn); } else if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryPassword) { SecureString password = new SecureString(); foreach (char c in parameters.Password) { password.AppendChar(c); } password.MakeReadOnly(); result = await app.AcquireTokenByUsernamePassword(scopes, parameters.UserId, password) .WithCorrelationId(parameters.ConnectionId) .ExecuteAsync(cancellationToken: cts.Token); SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Password auth mode. Expiry Time: {0}", result?.ExpiresOn); } else if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryInteractive || parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow) { // Fetch available accounts from 'app' instance System.Collections.Generic.IEnumerator <IAccount> accounts = (await app.GetAccountsAsync()).GetEnumerator(); IAccount account = default; if (accounts.MoveNext()) { if (!string.IsNullOrEmpty(parameters.UserId)) { do { IAccount currentVal = accounts.Current; if (string.Compare(parameters.UserId, currentVal.Username, StringComparison.InvariantCultureIgnoreCase) == 0) { account = currentVal; break; } }while (accounts.MoveNext()); } else { account = accounts.Current; } } if (null != account) { try { // If 'account' is available in 'app', we use the same to acquire token silently. // Read More on API docs: https://docs.microsoft.com/dotnet/api/microsoft.identity.client.clientapplicationbase.acquiretokensilent result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync(cancellationToken: cts.Token); SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (silent) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result?.ExpiresOn); } catch (MsalUiRequiredException) { // An 'MsalUiRequiredException' is thrown in the case where an interaction is required with the end user of the application, // for instance, if no refresh token was in the cache, or the user needs to consent, or re-sign-in (for instance if the password expired), // or the user needs to perform two factor authentication. result = await AcquireTokenInteractiveDeviceFlowAsync(app, scopes, parameters.ConnectionId, parameters.UserId, parameters.AuthenticationMethod, cts); SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (interactive) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result?.ExpiresOn); } } else { // If no existing 'account' is found, we request user to sign in interactively. result = await AcquireTokenInteractiveDeviceFlowAsync(app, scopes, parameters.ConnectionId, parameters.UserId, parameters.AuthenticationMethod, cts); SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (interactive) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result?.ExpiresOn); } } else { SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | {0} authentication mode not supported by ActiveDirectoryAuthenticationProvider class.", parameters.AuthenticationMethod); throw SQL.UnsupportedAuthenticationSpecified(parameters.AuthenticationMethod); } return(new SqlAuthenticationToken(result.AccessToken, result.ExpiresOn)); }
public void TestSetup() { expectedTenantId = null; expectedReplyUri = null; authCode = Guid.NewGuid().ToString(); options = new TokenCredentialOptions(); expectedToken = Guid.NewGuid().ToString(); expectedUserAssertion = Guid.NewGuid().ToString(); expiresOn = DateTimeOffset.Now.AddHours(1); result = new AuthenticationResult( expectedToken, false, null, expiresOn, expiresOn, TenantId, new MockAccount("username"), null, new[] { Scope }, Guid.NewGuid(), null, "Bearer"); mockConfidentialMsalClient = new MockMsalConfidentialClient() .WithSilentFactory( (_, _tenantId, _replyUri, _) => { Assert.AreEqual(expectedTenantId, _tenantId); Assert.AreEqual(expectedReplyUri, _replyUri); return(new ValueTask <AuthenticationResult>(result)); }) .WithAuthCodeFactory( (_, _tenantId, _replyUri, _) => { Assert.AreEqual(expectedTenantId, _tenantId); Assert.AreEqual(expectedReplyUri, _replyUri); return(result); }) .WithOnBehalfOfFactory( (_, _, userAssertion, _, _) => { Assert.AreEqual(expectedUserAssertion, userAssertion.Assertion); return(new ValueTask <AuthenticationResult>(result)); }) .WithClientFactory( (_, _tenantId) => { Assert.AreEqual(expectedTenantId, _tenantId); return(result); }); expectedCode = Guid.NewGuid().ToString(); mockPublicMsalClient = new MockMsalPublicClient(); deviceCodeResult = MockMsalPublicClient.GetDeviceCodeResult(deviceCode: expectedCode); mockPublicMsalClient.DeviceCodeResult = deviceCodeResult; var publicResult = new AuthenticationResult( expectedToken, false, null, expiresOn, expiresOn, TenantId, new MockAccount("username"), null, new[] { Scope }, Guid.NewGuid(), null, "Bearer"); mockPublicMsalClient.SilentAuthFactory = (_, tId) => { Assert.AreEqual(expectedTenantId, tId); return(publicResult); }; mockPublicMsalClient.DeviceCodeAuthFactory = (_, _) => { // Assert.AreEqual(tenantId, tId); return(publicResult); }; mockPublicMsalClient.InteractiveAuthFactory = (_, _, _, _, tenant, _, _) => { Assert.AreEqual(expectedTenantId, tenant, "TenantId passed to msal should match"); return(result); }; mockPublicMsalClient.SilentAuthFactory = (_, tenant) => { Assert.AreEqual(expectedTenantId, tenant, "TenantId passed to msal should match"); return(result); }; mockPublicMsalClient.ExtendedSilentAuthFactory = (_, _, _, tenant, _, _) => { Assert.AreEqual(expectedTenantId, tenant, "TenantId passed to msal should match"); return(result); }; mockPublicMsalClient.UserPassAuthFactory = (_, tenant) => { Assert.AreEqual(expectedTenantId, tenant, "TenantId passed to msal should match"); return(result); }; mockPublicMsalClient.RefreshTokenFactory = (_, _, _, _, tenant, _, _) => { Assert.AreEqual(expectedTenantId, tenant, "TenantId passed to msal should match"); return(result); }; }
public override TokenCredential GetTokenCredential(TokenCredentialOptions options) => InstrumentClient( new InteractiveBrowserCredential(TenantId, ClientId, options, null, mockPublicMsalClient));
private CredentialPipeline(TokenCredentialOptions options) { AuthorityHost = options.AuthorityHost; HttpPipeline = HttpPipelineBuilder.Build(options, Array.Empty <HttpPipelinePolicy>(), Array.Empty <HttpPipelinePolicy>(), new CredentialResponseClassifier()); }
public override TokenCredential GetTokenCredential(TokenCredentialOptions options) => InstrumentClient( new ClientSecretCredential(expectedTenantId, ClientId, "secret", options, null, mockConfidentialMsalClient));
public static CredentialPipeline GetInstance(TokenCredentialOptions options) { return(options is null ? s_singleton.Value : new CredentialPipeline(options)); }
public override TokenCredential GetTokenCredential(TokenCredentialOptions options) => InstrumentClient( new AuthorizationCodeCredential(TenantId, ClientId, clientSecret, authCode, options, mockConfidentialMsalClient));
public MockMsalPublicClient(CredentialPipeline pipeline, string tenantId, string clientId, string redirectUrl, TokenCredentialOptions options) : base(pipeline, tenantId, clientId, redirectUrl, options) { }