public async Task GetToken() { var tenantId = TestEnvironment.ServicePrincipalTenantId; var clientId = TestEnvironment.ServicePrincipalClientId; var secret = TestEnvironment.ServicePrincipalClientSecret; var options = InstrumentClientOptions(new TokenCredentialOptions()); var credential = new ClientSecretCredential(tenantId, clientId, secret, options); var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(AzureAuthorityHosts.AzurePublicCloud) }); // ensure we can initially acquire a token AccessToken token = await credential.GetTokenAsync(tokenRequestContext); Assert.IsNotNull(token.Token); // ensure subsequent calls before the token expires are served from the token cache AccessToken cachedToken = await credential.GetTokenAsync(tokenRequestContext); Assert.AreEqual(token.Token, cachedToken.Token); // ensure new credentials don't share tokens from the cache var credential2 = new ClientSecretCredential(tenantId, clientId, secret, options); AccessToken token2 = await credential2.GetTokenAsync(tokenRequestContext); if (Mode != RecordedTestMode.Playback && Mode != RecordedTestMode.None) { Assert.AreNotEqual(token.Token, token2.Token); } }
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; }
//MSAL doesn't cache Service Principal into msal.cache public override Task <IAccessToken> Authenticate(AuthenticationParameters parameters, CancellationToken cancellationToken) { var spParameters = parameters as ServicePrincipalParameters; var onPremise = spParameters.Environment.OnPremise; var tenantId = onPremise ? AdfsTenant : (string.Equals(parameters.TenantId, OrganizationsTenant, StringComparison.OrdinalIgnoreCase) ? null : parameters.TenantId); var resource = spParameters.Environment.GetEndpoint(spParameters.ResourceId) ?? spParameters.ResourceId; var scopes = AuthenticationHelpers.GetScope(onPremise, resource); var clientId = spParameters.ApplicationId; var authority = spParameters.Environment.ActiveDirectoryAuthority; var requestContext = new TokenRequestContext(scopes); var options = new ClientCertificateCredentialOptions() { AuthorityHost = new Uri(authority) }; if (!string.IsNullOrEmpty(spParameters.Thumbprint)) { //Service Principal with Certificate ClientCertificateCredential certCredential; if (!ClientCertCredentialMap.TryGetValue(spParameters.ApplicationId, out certCredential)) { //first time login var certificate = AzureSession.Instance.DataStore.GetCertificate(spParameters.Thumbprint); certCredential = new ClientCertificateCredential(tenantId, spParameters.ApplicationId, certificate, options); var tokenTask = certCredential.GetTokenAsync(requestContext, cancellationToken); return(MsalAccessToken.GetAccessTokenAsync(tokenTask, () => { ClientCertCredentialMap[spParameters.ApplicationId] = certCredential; }, spParameters.TenantId, spParameters.ApplicationId)); } else { var tokenTask = certCredential.GetTokenAsync(requestContext, cancellationToken); return(MsalAccessToken.GetAccessTokenAsync(tokenTask, spParameters.TenantId, spParameters.ApplicationId)); } } else if (spParameters.Secret != null) { // service principal with secret var secretCredential = new ClientSecretCredential(tenantId, spParameters.ApplicationId, spParameters.Secret.ConvertToString(), options); var tokenTask = secretCredential.GetTokenAsync(requestContext, cancellationToken); return(MsalAccessToken.GetAccessTokenAsync( tokenTask, spParameters.TenantId, spParameters.ApplicationId)); } else { throw new MsalException(MsalError.AuthenticationFailed, string.Format(AuthenticationFailedMessage, clientId)); } }
public async Task UsesTenantIdHint( [Values(null, TenantIdHint)] string tenantId, [Values(true)] bool allowMultiTenantAuthentication) { TestSetup(); var context = new TokenRequestContext(new[] { Scope }, tenantId: tenantId); expectedTenantId = TenantIdResolver.Resolve(TenantId, context); ClientSecretCredential client = InstrumentClient(new ClientSecretCredential(expectedTenantId, ClientId, "secret", options, null, mockConfidentialMsalClient)); var token = await client.GetTokenAsync(new TokenRequestContext(MockScopes.Default)); Assert.AreEqual(token.Token, expectedToken, "Should be the expected token value"); }
public void GetTokenIncorrectPassword() { var tenantId = TestEnvironment.ServicePrincipalTenantId; var clientId = TestEnvironment.ServicePrincipalClientId; var secret = "badsecret"; var options = InstrumentClientOptions(new TokenCredentialOptions()); var credential = new ClientSecretCredential(tenantId, clientId, secret, options); var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(AzureAuthorityHosts.AzurePublicCloud) }); // ensure we can initially acquire a token Assert.ThrowsAsync <AuthenticationFailedException>(async() => await credential.GetTokenAsync(tokenRequestContext)); }
public async Task VerifyClientSecretCredentialRequestAsync() { var response = new MockResponse(200); var expectedToken = "mock-msi-access-token"; response.SetContent($"{{ \"access_token\": \"{expectedToken}\", \"expires_in\": 3600 }}"); 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)); AccessToken actualToken = await client.GetTokenAsync(new TokenRequestContext(MockScopes.Default)); Assert.AreEqual(expectedToken, actualToken.Token); MockRequest request = mockTransport.SingleRequest; Assert.IsTrue(request.Content.TryComputeLength(out long contentLen)); var content = new byte[contentLen]; await request.Content.WriteToAsync(new MemoryStream(content), default); Assert.IsTrue(TryParseFormEncodedBody(content, out Dictionary <string, string> parsedBody)); Assert.IsTrue(parsedBody.TryGetValue("response_type", out string responseType) && responseType == "token"); Assert.IsTrue(parsedBody.TryGetValue("grant_type", out string grantType) && grantType == "client_credentials"); Assert.IsTrue(parsedBody.TryGetValue("client_id", out string actualClientId) && actualClientId == expectedClientId); Assert.IsTrue(parsedBody.TryGetValue("client_secret", out string actualClientSecret) && actualClientSecret == "secret"); Assert.IsTrue(parsedBody.TryGetValue("scope", out string actualScope) && actualScope == MockScopes.Default.ToString()); }
public async Task GetToken() { var tenantId = TestEnvironment.ServicePrincipalTenantId; var clientId = TestEnvironment.ServicePrincipalClientId; var secret = TestEnvironment.ServicePrincipalClientSecret; var cache = new MemoryTokenCache(); var options = InstrumentClientOptions(new ClientSecretCredentialOptions() { TokenCachePersistenceOptions = cache }); var credential = InstrumentClient(new ClientSecretCredential(tenantId, clientId, secret, options)); var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(new Uri(TestEnvironment.AuthorityHostUrl)) }); // ensure we can initially acquire a token AccessToken token = await credential.GetTokenAsync(tokenRequestContext); Assert.IsNotNull(token.Token); Assert.That(cache.CacheReadCount, Is.Not.Zero); Assert.That(cache.CacheUpdatedCount, Is.Not.Zero); // ensure subsequent calls before the token expires are served from the token cache AccessToken cachedToken = await credential.GetTokenAsync(tokenRequestContext); Assert.AreEqual(token.Token, cachedToken.Token); var options2 = InstrumentClientOptions(new ClientSecretCredentialOptions()); // ensure new credentials don't share tokens from the cache var credential2 = new ClientSecretCredential(tenantId, clientId, secret, options2); AccessToken token2 = await credential2.GetTokenAsync(tokenRequestContext); if (Mode != RecordedTestMode.Playback && Mode != RecordedTestMode.None) { Assert.AreNotEqual(token.Token, token2.Token); } }
public async Task TestGetAzureAdTokenAndAuthenticate() { var credential = new ClientSecretCredential(TestTenantId, TestClientId, TestClientSecret); ConfigurationManager <OpenIdConnectConfiguration> configManager = new ConfigurationManager <OpenIdConnectConfiguration>( "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever() ); var keys = configManager.GetConfigurationAsync().Result.SigningKeys; var p = new TokenValidationParameters() { ValidateLifetime = true, ValidateAudience = false, IssuerValidator = (string issuer, SecurityToken securityToken, TokenValidationParameters validationParameters) => { if (issuer.StartsWith(IssuerEndpoint)) { return(IssuerEndpoint); } throw new SecurityTokenInvalidIssuerException(); }, ValidateIssuerSigningKey = true, IssuerSigningKeys = keys, }; var handler = new JwtSecurityTokenHandler(); IdentityModelEventSource.ShowPII = true; var accessToken = await credential.GetTokenAsync(new TokenRequestContext(DefaultScopes)); var claims = handler.ValidateToken(accessToken.Token, p, out var validToken); Assert.NotNull(validToken); }
public async Task VerifyClientSecretCredentialExceptionAsync() { string expectedInnerExMessage = Guid.NewGuid().ToString(); var mockAadClient = new MockAadIdentityClient(() => { throw new MockClientException(expectedInnerExMessage); }); ClientSecretCredential credential = InstrumentClient(new ClientSecretCredential(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), CredentialPipeline.GetInstance(null), mockAadClient)); var ex = Assert.ThrowsAsync <AuthenticationFailedException>(async() => await credential.GetTokenAsync(new TokenRequestContext(MockScopes.Default))); Assert.IsNotNull(ex.InnerException); Assert.IsInstanceOf(typeof(MockClientException), ex.InnerException); Assert.AreEqual(expectedInnerExMessage, ex.InnerException.Message); await Task.CompletedTask; }