public async Task GivenNoLinkAndEmailClaim_ItDisplaysLogOnViewWithEmailPrefilled() { // Arrange var cred = CredentialBuilder.CreateExternalCredential("MicrosoftAccount", "blorg", "Bloog"); var msAuther = new MicrosoftAccountAuthenticator(); var msaUI = msAuther.GetUI(); GetMock <AuthenticationService>(); // Force a mock to be created var controller = GetController <AuthenticationController>(); GetMock <AuthenticationService>() .Setup(x => x.AuthenticateExternalLogin(controller.OwinContext)) .CompletesWith(new AuthenticateExternalLoginResult() { ExternalIdentity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Email, "*****@*****.**") }), Authenticator = msAuther }); // Act var result = await controller.LinkExternalAccount("theReturnUrl"); // Assert var model = ResultAssert.IsView <LogOnViewModel>(result, viewName: "LogOn"); Assert.Equal(msaUI.AccountNoun, model.External.ProviderAccountNoun); Assert.Null(model.External.AccountName); Assert.False(model.External.FoundExistingUser); Assert.Equal("*****@*****.**", model.SignIn.UserNameOrEmail); Assert.Equal("*****@*****.**", model.Register.EmailAddress); }
private Task <SecurityPolicyResult> EvaluateAsync(string userTenantId) { var credentialBuilder = new CredentialBuilder(); var fakes = new Fakes(); if (!string.IsNullOrEmpty(userTenantId)) { fakes.User.Credentials.Add( credentialBuilder.CreateExternalCredential( issuer: "AzureActiveDirectory", value: "value", identity: "identity", tenantId: userTenantId)); } foreach (var policy in RequireOrganizationTenantPolicy.Create(TenantId).Policies) { fakes.Organization.SecurityPolicies.Add(policy); } var context = new UserSecurityPolicyEvaluationContext( fakes.Organization.SecurityPolicies, sourceAccount: fakes.Organization, targetAccount: fakes.User ); return(RequireOrganizationTenantPolicy .Create() .EvaluateAsync(context)); }
public async Task GivenAssociatedLocalUser_ItCreatesASessionAndSafeRedirectsToReturnUrl() { // Arrange var fakes = Get <Fakes>(); var mockConfig = GetMock <IGalleryConfigurationService>(); mockConfig.Setup(x => x.Current).Returns(new AppConfiguration()); GetMock <AuthenticationService>(); // Force a mock to be created var controller = GetController <AuthenticationController>(); var cred = CredentialBuilder.CreateExternalCredential("MicrosoftAccount", "blorg", "Bloog"); var authUser = new AuthenticatedUser( fakes.CreateUser("test", cred), cred); GetMock <AuthenticationService>() .Setup(x => x.AuthenticateExternalLogin(controller.OwinContext)) .CompletesWith(new AuthenticateExternalLoginResult() { ExternalIdentity = new ClaimsIdentity(), Authentication = authUser }); // Act var result = await controller.LinkExternalAccount("theReturnUrl"); // Assert ResultAssert.IsSafeRedirectTo(result, "theReturnUrl"); GetMock <AuthenticationService>() .Verify(x => x.CreateSessionAsync(controller.OwinContext, authUser)); }
public async Task GivenAssociatedLocalAdminUser_ItChallengesWhenNotUsingRequiredExternalProvider(string providerUsedForLogin, bool shouldChallenge) { // Arrange var enforcedProvider = "AzureActiveDirectory"; var config = Get <ConfigurationService>(); config.Current = new AppConfiguration() { ConfirmEmailAddresses = false, EnforcedAuthProviderForAdmin = enforcedProvider }; GetMock <AuthenticationService>(); // Force a mock to be created var controller = GetController <AuthenticationController>(); var cred = CredentialBuilder.CreateExternalCredential(providerUsedForLogin, "blorg", "Bloog"); var authUser = new AuthenticatedUser( Fakes.CreateUser("test", cred), cred); authUser.User.Roles.Add(new Role { Name = Constants.AdminRoleName }); GetMock <AuthenticationService>() .Setup(x => x.AuthenticateExternalLogin(controller.OwinContext)) .CompletesWith(new AuthenticateExternalLoginResult() { ExternalIdentity = new ClaimsIdentity(), Authentication = authUser }); if (shouldChallenge) { GetMock <AuthenticationService>() .Setup(x => x.Challenge(enforcedProvider, It.IsAny <string>())) .Returns(new ChallengeResult(enforcedProvider, null)) .Verifiable(); } else { GetMock <AuthenticationService>() .Setup(x => x.CreateSession(controller.OwinContext, authUser.User)) .Verifiable(); } // Act var result = await controller.LinkExternalAccount("theReturnUrl"); // Assert if (shouldChallenge) { ResultAssert.IsChallengeResult(result, enforcedProvider); } else { ResultAssert.IsSafeRedirectTo(result, "theReturnUrl"); GetMock <AuthenticationService>().VerifyAll(); } }
public async Task GivenValidExternalAuth_ItCreatesAccountAndLinksCredential() { // Arrange var authUser = new AuthenticatedUser( new User("theUsername") { UnconfirmedEmailAddress = "*****@*****.**", EmailConfirmationToken = "t0k3n" }, new Credential()); var externalCred = CredentialBuilder.CreateExternalCredential("MicrosoftAccount", "blorg", "Bloog"); GetMock <AuthenticationService>() .Setup(x => x.Register("theUsername", "theEmailAddress", externalCred)) .CompletesWith(authUser); var controller = GetController <AuthenticationController>(); GetMock <AuthenticationService>() .Setup(x => x.CreateSessionAsync(controller.OwinContext, authUser)) .Returns(Task.FromResult(0)) .Verifiable(); GetMock <AuthenticationService>() .Setup(x => x.ReadExternalLoginCredential(controller.OwinContext)) .CompletesWith(new AuthenticateExternalLoginResult() { ExternalIdentity = new ClaimsIdentity(), Credential = externalCred }); // Simulate the model state error that will be added when doing an external account registration (since password is not present) controller.ModelState.AddModelError("Register.Password", "Password is required"); // Act var result = await controller.Register( new LogOnViewModel() { Register = new RegisterViewModel { Username = "******", EmailAddress = "theEmailAddress", } }, "/theReturnUrl", linkingAccount : true); // Assert GetMock <AuthenticationService>().VerifyAll(); var expectedAddress = new MailAddress(authUser.User.UnconfirmedEmailAddress, authUser.User.Username); GetMock <IMessageService>() .Verify(x => x.SendNewAccountEmail( expectedAddress, "https://nuget.local/account/confirm/theUsername/t0k3n")); ResultAssert.IsSafeRedirectTo(result, "/theReturnUrl"); }
public async Task GivenValidExternalAuth_ItLinksCredentialSendsEmailAndLogsIn() { // Arrange var authUser = new AuthenticatedUser( new User("theUsername") { EmailAddress = "*****@*****.**" }, new Credential() { Type = "Foo" }); var externalCred = CredentialBuilder.CreateExternalCredential("MicrosoftAccount", "blorg", "Bloog"); GetMock <AuthenticationService>() .Setup(x => x.Authenticate(authUser.User.Username, "thePassword")) .CompletesWith(authUser); GetMock <AuthenticationService>() .Setup(x => x.AddCredential(authUser.User, externalCred)) .Completes() .Verifiable(); GetMock <IMessageService>() .Setup(x => x.SendCredentialAddedNotice(authUser.User, externalCred)) .Verifiable(); var controller = GetController <AuthenticationController>(); GetMock <AuthenticationService>() .Setup(x => x.CreateSessionAsync(controller.OwinContext, It.IsAny <AuthenticatedUser>())) .Returns(Task.FromResult(0)) .Verifiable(); GetMock <AuthenticationService>() .Setup(x => x.ReadExternalLoginCredential(controller.OwinContext)) .CompletesWith(new AuthenticateExternalLoginResult { ExternalIdentity = new ClaimsIdentity(), Credential = externalCred }); // Act var result = await controller.SignIn( new LogOnViewModel( new SignInViewModel( authUser.User.Username, "thePassword")), "theReturnUrl", linkingAccount : true); // Assert ResultAssert.IsSafeRedirectTo(result, "theReturnUrl"); GetMock <AuthenticationService>().VerifyAll(); GetMock <IMessageService>().VerifyAll(); }
public async virtual Task <AuthenticateExternalLoginResult> ReadExternalLoginCredential(IOwinContext context) { var result = await context.Authentication.AuthenticateAsync(AuthenticationTypes.External); if (result == null) { _trace.Information("No external login found."); return(new AuthenticateExternalLoginResult()); } var idClaim = result.Identity.FindFirst(ClaimTypes.NameIdentifier); if (idClaim == null) { _trace.Error("External Authentication is missing required claim: " + ClaimTypes.NameIdentifier); return(new AuthenticateExternalLoginResult()); } var nameClaim = result.Identity.FindFirst(ClaimTypes.Name); if (nameClaim == null) { _trace.Error("External Authentication is missing required claim: " + ClaimTypes.Name); return(new AuthenticateExternalLoginResult()); } var emailClaim = result.Identity.FindFirst(ClaimTypes.Email); string emailSuffix = emailClaim == null ? String.Empty : (" <" + emailClaim.Value + ">"); Authenticator auther; string authenticationType = idClaim.Issuer; if (!Authenticators.TryGetValue(idClaim.Issuer, out auther)) { foreach (var authenticator in Authenticators.Values) { if (authenticator.TryMapIssuerToAuthenticationType(idClaim.Issuer, out authenticationType)) { auther = authenticator; break; } } } return(new AuthenticateExternalLoginResult() { Authentication = null, ExternalIdentity = result.Identity, Authenticator = auther, Credential = CredentialBuilder.CreateExternalCredential(authenticationType, idClaim.Value, nameClaim.Value + emailSuffix) }); }
public async Task GivenNoLinkButEmailMatchingLocalUser_ItDisplaysLogOnViewPresetForSignIn() { // Arrange var fakes = Get <Fakes>(); var existingUser = new User("existingUser") { EmailAddress = "*****@*****.**" }; var cred = CredentialBuilder.CreateExternalCredential("MicrosoftAccount", "blorg", "Bloog"); var msAuther = new MicrosoftAccountAuthenticator(); var msaUI = msAuther.GetUI(); var authUser = new AuthenticatedUser( fakes.CreateUser("test", cred), cred); GetMock <AuthenticationService>(); // Force a mock to be created GetMock <IUserService>() .Setup(u => u.FindByEmailAddress(existingUser.EmailAddress)) .Returns(existingUser); var controller = GetController <AuthenticationController>(); GetMock <AuthenticationService>() .Setup(x => x.AuthenticateExternalLogin(controller.OwinContext)) .CompletesWith(new AuthenticateExternalLoginResult() { ExternalIdentity = new ClaimsIdentity(new [] { new Claim(ClaimTypes.Email, existingUser.EmailAddress) }), Authenticator = msAuther }); // Act var result = await controller.LinkExternalAccount("theReturnUrl"); // Assert var model = ResultAssert.IsView <LogOnViewModel>(result, viewName: "LogOn"); Assert.Equal(msaUI.AccountNoun, model.External.ProviderAccountNoun); Assert.Null(model.External.AccountName); Assert.True(model.External.FoundExistingUser); Assert.Equal(existingUser.EmailAddress, model.SignIn.UserNameOrEmail); Assert.Equal(existingUser.EmailAddress, model.Register.EmailAddress); }
private Task <SecurityPolicyResult> EvaluateAsync(string userTenantId) { var credentialBuilder = new CredentialBuilder(); var fakes = new Fakes(); if (!string.IsNullOrEmpty(userTenantId)) { // We can only have a single AAD account, remove previous one if present. var aadCredential = fakes.User.Credentials.Single(c => c.Type.Contains(CredentialTypes.External.AzureActiveDirectoryAccount)); if (aadCredential != null) { fakes.User.Credentials.Remove(aadCredential); } // Add the new AAD credential fakes.User.Credentials.Add( credentialBuilder.CreateExternalCredential( issuer: "AzureActiveDirectory", value: "value", identity: "identity", tenantId: userTenantId)); } foreach (var policy in RequireOrganizationTenantPolicy.Create(TenantId).Policies) { fakes.Organization.SecurityPolicies.Add(policy); } var context = new UserSecurityPolicyEvaluationContext( fakes.Organization.SecurityPolicies, sourceAccount: fakes.Organization, targetAccount: fakes.User ); return(RequireOrganizationTenantPolicy .Create() .EvaluateAsync(context)); }
public void FiltersOutUnsupportedCredentials() { // Arrange var credentialBuilder = new CredentialBuilder(); var credentials = new List <Credential> { credentialBuilder.CreatePasswordCredential("v3"), TestCredentialHelper.CreatePbkdf2Password("pbkdf2"), TestCredentialHelper.CreateSha1Password("sha1"), TestCredentialHelper.CreateV1ApiKey(Guid.NewGuid(), Fakes.ExpirationForApiKeyV1), TestCredentialHelper.CreateV2ApiKey(Guid.NewGuid(), Fakes.ExpirationForApiKeyV1), TestCredentialHelper.CreateV2VerificationApiKey(Guid.NewGuid()), credentialBuilder.CreateExternalCredential("MicrosoftAccount", "blarg", "Bloog"), new Credential { Type = "unsupported" } }; var user = new User { Username = "******", Credentials = credentials }; // Act var userAuditRecord = new UserAuditRecord(user, AuditedUserAction.AddCredential); // Assert var auditRecords = userAuditRecord.Credentials.ToDictionary(c => c.Type); Assert.Equal(7, auditRecords.Count); Assert.True(auditRecords.ContainsKey(credentials[0].Type)); Assert.True(auditRecords.ContainsKey(credentials[1].Type)); Assert.True(auditRecords.ContainsKey(credentials[2].Type)); Assert.True(auditRecords.ContainsKey(credentials[3].Type)); Assert.True(auditRecords.ContainsKey(credentials[4].Type)); Assert.True(auditRecords.ContainsKey(credentials[5].Type)); Assert.True(auditRecords.ContainsKey(credentials[6].Type)); }
public async Task GivenAdminLogsInWithExternalIdentity_ItChallengesWhenNotUsingRequiredExternalProvider(string providerUsedForLogin, bool shouldChallenge) { // Arrange var enforcedProvider = "AzureActiveDirectory"; var mockConfig = GetMock <IGalleryConfigurationService>(); mockConfig.Setup(x => x.Current).Returns(new AppConfiguration { ConfirmEmailAddresses = false, EnforcedAuthProviderForAdmin = enforcedProvider }); var externalCred = CredentialBuilder.CreateExternalCredential(providerUsedForLogin, "blorg", "Bloog"); var authUser = new AuthenticatedUser( new User("theUsername") { UnconfirmedEmailAddress = "*****@*****.**", EmailConfirmationToken = "t0k3n", Roles = { new Role { Name = Constants.AdminRoleName } } }, externalCred); GetMock <AuthenticationService>() .Setup(x => x.Register("theUsername", "theEmailAddress", externalCred)) .CompletesWith(authUser); EnableAllAuthenticators(Get <AuthenticationService>()); var controller = GetController <AuthenticationController>(); if (shouldChallenge) { GetMock <AuthenticationService>() .Setup(x => x.Challenge(enforcedProvider, It.IsAny <string>())) .Returns(new ChallengeResult(enforcedProvider, null)) .Verifiable(); } else { GetMock <AuthenticationService>() .Setup(x => x.CreateSessionAsync(controller.OwinContext, authUser)) .Returns(Task.FromResult(0)) .Verifiable(); } GetMock <AuthenticationService>() .Setup(x => x.ReadExternalLoginCredential(controller.OwinContext)) .CompletesWith(new AuthenticateExternalLoginResult() { ExternalIdentity = new ClaimsIdentity(), Credential = externalCred }); // Act var result = await controller.Register( new LogOnViewModel() { Register = new RegisterViewModel { Username = "******", EmailAddress = "theEmailAddress", } }, "/theReturnUrl", linkingAccount : true); // Assert if (shouldChallenge) { ResultAssert.IsChallengeResult(result, enforcedProvider); } else { ResultAssert.IsSafeRedirectTo(result, "/theReturnUrl"); } GetMock <AuthenticationService>().VerifyAll(); }
public async Task GivenAdminLogsInWithValidExternalAuth_ItChallengesWhenNotUsingRequiredExternalProvider(string providerUsedForLogin, bool shouldChallenge) { var enforcedProvider = "AzureActiveDirectory"; var config = Get <ConfigurationService>(); config.Current = new AppConfiguration() { ConfirmEmailAddresses = false, EnforcedAuthProviderForAdmin = enforcedProvider }; var externalCred = CredentialBuilder.CreateExternalCredential(providerUsedForLogin, "blorg", "Bloog"); var authUser = new AuthenticatedUser( new User("theUsername") { UnconfirmedEmailAddress = "*****@*****.**", Roles = { new Role { Name = Constants.AdminRoleName } } }, externalCred); GetMock <AuthenticationService>() .Setup(x => x.Authenticate(authUser.User.Username, "thePassword")) .CompletesWith(authUser); GetMock <AuthenticationService>() .Setup(x => x.AddCredential(authUser.User, externalCred)) .Completes() .Verifiable(); GetMock <IMessageService>() .Setup(x => x.SendCredentialAddedNotice(authUser.User, externalCred)) .Verifiable(); EnableAllAuthenticators(Get <AuthenticationService>()); var controller = GetController <AuthenticationController>(); if (shouldChallenge) { GetMock <AuthenticationService>() .Setup(x => x.Challenge(enforcedProvider, It.IsAny <string>())) .Returns(new ChallengeResult(enforcedProvider, null)) .Verifiable(); } else { GetMock <AuthenticationService>() .Setup(x => x.CreateSession(controller.OwinContext, authUser.User)) .Verifiable(); } GetMock <AuthenticationService>() .Setup(x => x.ReadExternalLoginCredential(controller.OwinContext)) .CompletesWith(new AuthenticateExternalLoginResult() { ExternalIdentity = new ClaimsIdentity(), Credential = externalCred }); // Act var result = await controller.SignIn( new LogOnViewModel( new SignInViewModel( authUser.User.Username, "thePassword")), "theReturnUrl", linkingAccount : true); // Assert if (shouldChallenge) { ResultAssert.IsChallengeResult(result, enforcedProvider); } else { ResultAssert.IsSafeRedirectTo(result, "theReturnUrl"); } GetMock <AuthenticationService>().VerifyAll(); GetMock <IMessageService>().VerifyAll(); }
public async Task WritesAuditRecordForTheRemovedCredential() { // Arrange var credentialBuilder = new CredentialBuilder(); var fakes = Get<Fakes>(); var cred = credentialBuilder.CreateExternalCredential("flarg", "glarb", "blarb"); var user = fakes.CreateUser("test", credentialBuilder.CreatePasswordCredential(Fakes.Password), cred); var authService = Get<AuthenticationService>(); // Act await authService.RemoveCredential(user, cred); // Assert Assert.True(authService.Auditing.WroteRecord<UserAuditRecord>(ar => ar.Action == AuditedUserAction.RemoveCredential && ar.Username == user.Username && ar.AffectedCredential.Length == 1 && ar.AffectedCredential[0].Type == cred.Type && ar.AffectedCredential[0].Identity == cred.Identity && ar.AffectedCredential[0].Value == cred.Value)); }
public async Task RemovesTheCredentialFromTheDataStore() { // Arrange var credentialBuilder = new CredentialBuilder(); var fakes = Get<Fakes>(); var cred = credentialBuilder.CreateExternalCredential("flarg", "glarb", "blarb"); var user = fakes.CreateUser("test", credentialBuilder.CreatePasswordCredential(Fakes.Password), cred); var authService = Get<AuthenticationService>(); // Act await authService.RemoveCredential(user, cred); // Assert Assert.DoesNotContain(cred, user.Credentials); Assert.DoesNotContain(cred, authService.Entities.Credentials); authService.Entities.VerifyCommitChanges(); }