public async Task GivenNoLinkButEmailMatchingLocalUser_ItDisplaysLogOnViewPresetForSignIn() { // Arrange var fakes = Get <Fakes>(); var existingUser = new User("existingUser") { EmailAddress = "*****@*****.**" }; var cred = new 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: LinkExternalViewName); 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); }
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; if (!Authenticators.TryGetValue(idClaim.Issuer, out auther)) { auther = null; } return(new AuthenticateExternalLoginResult() { Authentication = null, ExternalIdentity = result.Identity, Authenticator = auther, Credential = CredentialBuilder.CreateExternalCredential(idClaim.Issuer, idClaim.Value, nameClaim.Value + emailSuffix) }); }
public virtual async Task <bool> ChangePassword(User user, string oldPassword, string newPassword) { var hasPassword = user.Credentials.Any( c => c.Type.StartsWith(CredentialTypes.Password.Prefix, StringComparison.OrdinalIgnoreCase)); Credential _; if (hasPassword && !ValidatePasswordCredential(user.Credentials, oldPassword, out _)) { // Invalid old password! return(false); } // Replace/Set password credential var cred = CredentialBuilder.CreatePbkdf2Password(newPassword); await ReplaceCredentialInternal(user, cred); return(true); }
public virtual async Task <AuthenticatedUser> Register(string username, string emailAddress, Credential credential) { var existingUser = Entities.Users .FirstOrDefault(u => u.Username == username || u.EmailAddress == emailAddress); if (existingUser != null) { if (String.Equals(existingUser.Username, username, StringComparison.OrdinalIgnoreCase)) { throw new EntityException(Strings.UsernameNotAvailable, username); } else { throw new EntityException(Strings.EmailAddressBeingUsed, emailAddress); } } var apiKey = Guid.NewGuid(); var newUser = new User(username) { EmailAllowed = true, UnconfirmedEmailAddress = emailAddress, EmailConfirmationToken = CryptographyService.GenerateToken(), CreatedUtc = DateTime.UtcNow }; // Add a credential for the password and the API Key newUser.Credentials.Add(CredentialBuilder.CreateV1ApiKey(apiKey)); newUser.Credentials.Add(credential); if (!Config.ConfirmEmailAddresses) { newUser.ConfirmEmailAddress(); } // Write an audit record await Auditing.SaveAuditRecord(new UserAuditRecord(newUser, UserAuditAction.Registered)); Entities.Users.Add(newUser); Entities.SaveChanges(); return(new AuthenticatedUser(newUser, credential)); }
public CredentialStoreBuilder WithDefaultCredentials() { Credential cred1 = new CredentialBuilder("cred_01") .WithBirthdate(1994, 10, 26) .WithCreationDate(2000, 1, 2) .AddRole(RoleData.Role_01_Admin) .Build(); Credential cred2 = new CredentialBuilder("cred_02") .WithBirthdate(1998, 10, 26) .WithCreationDate(1998, 1, 2) .AddRole(RoleData.Role_02_User) .Build(); CredentialList.Add(cred1); CredentialList.Add(cred2); return(this); }
public void MigratesPasswordIfHashAlgorithmIsNotPBKDF2() { // Arrange var service = Get <AuthenticationService>(); var user = Fakes.CreateUser( "tempUser", CredentialBuilder.CreateSha1Password("oldpwd")); service.Entities .Set <User>() .Add(user); // Act var changed = service.ChangePassword(user.Username, "oldpwd", "newpwd"); // Assert var cred = user.Credentials.Single(c => c.Type.StartsWith(CredentialTypes.Password.Prefix, StringComparison.OrdinalIgnoreCase)); Assert.Equal(CredentialTypes.Password.Pbkdf2, cred.Type); Assert.True(VerifyPasswordHash(cred.Value, Constants.PBKDF2HashAlgorithmId, "newpwd")); service.Entities.VerifyCommitChanges(); }
public void UpdatesThePasswordCredential() { // Arrange var service = Get <AuthenticationService>(); var user = Fakes.CreateUser( "tempUser", CredentialBuilder.CreatePbkdf2Password("oldpwd")); service.Entities .Set <User>() .Add(user); // Act var changed = service.ChangePassword(user.Username, "oldpwd", "newpwd"); // Assert var cred = user.Credentials.Single(); Assert.Equal(CredentialTypes.Password.Pbkdf2, cred.Type); Assert.True(VerifyPasswordHash(cred.Value, Constants.PBKDF2HashAlgorithmId, "newpwd")); service.Entities.VerifyCommitChanges(); }
public async Task GivenMatchingApiKey_ItReturnsTicketWithUserNameAndRoles() { // Arrange Guid apiKey = Guid.NewGuid(); var user = new User() { Username = "******", EmailAddress = "*****@*****.**" }; TestableApiKeyAuthenticationHandler handler = await TestableApiKeyAuthenticationHandler.CreateAsync(new ApiKeyAuthenticationOptions()); handler.OwinContext.Request.Headers.Set( Constants.ApiKeyHeaderName, apiKey.ToString().ToLowerInvariant()); handler.MockAuth.SetupAuth(CredentialBuilder.CreateV1ApiKey(apiKey), user); // Act var ticket = await handler.InvokeAuthenticateCoreAsync(); // Assert Assert.NotNull(ticket); Assert.Equal(apiKey.ToString().ToLower(), ticket.Identity.GetClaimOrDefault(NuGetClaims.ApiKey)); }
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)); }
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 async Task GivenMatchingApiKeyWithOwnerScopeOfOrganization_ItSetsUserInOwinEnvironment(bool isAdmin) { // Arrange var organization = new Organization() { Key = 2345 }; var user = new User { Key = 1234, Username = "******", EmailAddress = "*****@*****.**" }; user.Organizations.Add(new Membership { OrganizationKey = 2345, Organization = organization, IsAdmin = isAdmin }); TestableApiKeyAuthenticationHandler handler = await TestableApiKeyAuthenticationHandler.CreateAsync(new ApiKeyAuthenticationOptions()); var apiKeyCredential = new CredentialBuilder().CreateApiKey(Fakes.ExpirationForApiKeyV1, out string plaintextApiKey); apiKeyCredential.Scopes.Add(new Scope(2345, "thePackage", "theAction")); handler.OwinContext.Request.Headers.Set( ServicesConstants.ApiKeyHeaderName, plaintextApiKey); handler.MockAuth.SetupAuth(apiKeyCredential, user, credentialValue: plaintextApiKey); // Act await handler.InvokeAuthenticateCoreAsync(); // Assert var authUser = Assert.IsType <AuthenticatedUser>( handler.OwinContext.Environment[ServicesConstants.CurrentUserOwinEnvironmentKey]); Assert.Same(user, authUser.User); }
public void GivenMultipleMatchingCredentials_ItThrows() { // Arrange var service = Get <AuthenticationService>(); var entities = Get <IEntitiesContext>(); var cred = CredentialBuilder.CreateV1ApiKey(); cred.Key = 42; var creds = entities.Set <Credential>(); creds.Add(cred); creds.Add(CredentialBuilder.CreateV1ApiKey(Guid.Parse(cred.Value))); // Act var ex = Assert.Throws <InvalidOperationException>(() => service.Authenticate(CredentialBuilder.CreateV1ApiKey(Guid.Parse(cred.Value)))); // Assert Assert.Equal(String.Format( CultureInfo.CurrentCulture, Strings.MultipleMatchingCredentials, cred.Type, cred.Key), ex.Message); }
public async Task GivenMatchingApiKey_ItSetsUserInOwinEnvironment() { // Arrange Guid apiKey = Guid.NewGuid(); var user = new User() { Username = "******", EmailAddress = "*****@*****.**" }; TestableApiKeyAuthenticationHandler handler = await TestableApiKeyAuthenticationHandler.CreateAsync(new ApiKeyAuthenticationOptions()); handler.OwinContext.Request.Headers.Set( Constants.ApiKeyHeaderName, apiKey.ToString().ToLowerInvariant()); handler.MockAuth.SetupAuth(CredentialBuilder.CreateV1ApiKey(apiKey), user); // Act await handler.InvokeAuthenticateCoreAsync(); // Assert var authUser = Assert.IsType <AuthenticatedUser>( handler.OwinContext.Environment[Constants.CurrentUserOwinEnvironmentKey]); Assert.Same(user, authUser.User); }
public async Task GivenMatchingApiKeyWithNoOwnerScope_ItSetsUserInOwinEnvironment() { // Arrange var user = new User { Username = "******", EmailAddress = "*****@*****.**" }; TestableApiKeyAuthenticationHandler handler = await TestableApiKeyAuthenticationHandler.CreateAsync(new ApiKeyAuthenticationOptions()); var apiKeyCredential = new CredentialBuilder().CreateApiKey(Fakes.ExpirationForApiKeyV1, out string plaintextApiKey); handler.OwinContext.Request.Headers.Set( ServicesConstants.ApiKeyHeaderName, plaintextApiKey); handler.MockAuth.SetupAuth(apiKeyCredential, user, credentialValue: plaintextApiKey); // Act await handler.InvokeAuthenticateCoreAsync(); // Assert var authUser = Assert.IsType <AuthenticatedUser>( handler.OwinContext.Environment[ServicesConstants.CurrentUserOwinEnvironmentKey]); Assert.Same(user, authUser.User); }
public async Task GivenValidExternalAuth_ItCreatesAccountAndLinksCredential() { // Arrange var authUser = new AuthenticatedUser( new User("theUsername") { UnconfirmedEmailAddress = "*****@*****.**", EmailConfirmationToken = "t0k3n" }, new Credential()); var externalCred = new 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 = new 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 Task ResetsPasswordCredential() { // Arrange var oldCred = new CredentialBuilder().CreatePasswordCredential("thePassword"); var user = new User { Username = "******", EmailAddress = "*****@*****.**", PasswordResetToken = "some-token", PasswordResetTokenExpirationDate = DateTime.UtcNow.AddDays(1), Credentials = new List<Credential> { oldCred } }; var authService = Get<AuthenticationService>(); authService.Entities.Users.Add(user); // Act var result = await authService.ResetPasswordWithToken("user", "some-token", "new-password"); // Assert Assert.NotNull(result); var newCred = user.Credentials.Single(); Assert.Same(result, newCred); Assert.Equal(CredentialBuilder.LatestPasswordType, newCred.Type); Assert.True(VerifyPasswordHash(newCred.Value, CredentialBuilder.LatestPasswordType, "new-password")); authService.Entities.VerifyCommitChanges(); Assert.Equal(0, user.FailedLoginCount); Assert.Null(user.LastFailedLoginUtc); }
private TestableApiKeyAuthenticationHandler() { Logger = (MockLogger = new Mock<ILogger>()).Object; Auth = (MockAuth = new Mock<AuthenticationService>()).Object; CredentialBuilder = new CredentialBuilder(); }
public async Task GivenAdminLogsInWithValidExternalAuth_ItChallengesWhenNotUsingRequiredExternalProvider(string providerUsedForLogin, bool shouldChallenge) { var enforcedProvider = "AzureActiveDirectory"; var mockConfig = GetMock <IGalleryConfigurationService>(); mockConfig.Setup(x => x.Current).Returns(new AppConfiguration { ConfirmEmailAddresses = false, EnforcedAuthProviderForAdmin = enforcedProvider }); var externalCred = new CredentialBuilder().CreateExternalCredential(providerUsedForLogin, "blorg", "Bloog"); var authUser = new AuthenticatedUser( new User("theUsername") { UnconfirmedEmailAddress = "*****@*****.**", Roles = { new Role { Name = Constants.AdminRoleName } } }, externalCred); var authResult = new PasswordAuthenticationResult(PasswordAuthenticationResult.AuthenticationResult.Success, authUser); GetMock <AuthenticationService>() .Setup(x => x.Authenticate(authUser.User.Username, "thePassword")) .CompletesWith(authResult); 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.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 if (shouldChallenge) { ResultAssert.IsChallengeResult(result, enforcedProvider); } else { ResultAssert.IsSafeRedirectTo(result, "theReturnUrl"); } GetMock <AuthenticationService>().VerifyAll(); GetMock <IMessageService>().VerifyAll(); }
public async Task GivenNoLinkButEmailMatchingLocalUser_ItDisplaysLogOnViewPresetForSignIn() { // Arrange var fakes = Get<Fakes>(); var existingUser = new User("existingUser") { EmailAddress = "*****@*****.**" }; var cred = new 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); }
public async Task GivenAssociatedLocalAdminUser_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 fakes = Get<Fakes>(); GetMock<AuthenticationService>(); // Force a mock to be created var controller = GetController<AuthenticationController>(); var cred = new 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.CreateSessionAsync(controller.OwinContext, authUser)) .Returns(Task.FromResult(0)) .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 GivenMatchingApiKey_ItSetsUserInOwinEnvironment() { // Arrange var user = new User { Username = "******", EmailAddress = "*****@*****.**" }; TestableApiKeyAuthenticationHandler handler = await TestableApiKeyAuthenticationHandler.CreateAsync(new ApiKeyAuthenticationOptions()); var apiKeyCredential = new CredentialBuilder().CreateApiKey(Fakes.ExpirationForApiKeyV1); handler.OwinContext.Request.Headers.Set( Constants.ApiKeyHeaderName, apiKeyCredential.Value.ToLowerInvariant()); handler.MockAuth.SetupAuth(apiKeyCredential, user); // Act await handler.InvokeAuthenticateCoreAsync(); // Assert var authUser = Assert.IsType<AuthenticatedUser>( handler.OwinContext.Environment[Constants.CurrentUserOwinEnvironmentKey]); Assert.Same(user, authUser.User); }
public void GivenATokenCredential_ItDescribesItCorrectly() { // Arrange var cred = new CredentialBuilder().CreateApiKey(Fakes.ExpirationForApiKeyV1); var authService = Get<AuthenticationService>(); // Act var description = authService.DescribeCredential(cred); // Assert Assert.Equal(cred.Type, description.Type); Assert.Equal(Strings.CredentialType_ApiKey, description.TypeCaption); Assert.Null(description.Identity); Assert.Equal(cred.Value, description.Value); Assert.Equal(cred.Created, description.Created); Assert.Equal(cred.Expires, description.Expires); Assert.Equal(cred.HasExpired, description.HasExpired); Assert.Equal(CredentialKind.Token, description.Kind); Assert.Null(description.AuthUI); }
public void GivenAnExternalCredential_ItDescribesItCorrectly() { // Arrange var cred = new CredentialBuilder().CreateExternalCredential("MicrosoftAccount", "abc123", "Test User"); var msftAuther = new MicrosoftAccountAuthenticator(); var authService = Get<AuthenticationService>(); // Act var description = authService.DescribeCredential(cred); // Assert Assert.Equal(cred.Type, description.Type); Assert.Equal(msftAuther.GetUI().Caption, description.TypeCaption); Assert.Equal(cred.Identity, description.Identity); Assert.True(string.IsNullOrEmpty(description.Value)); Assert.Equal(CredentialKind.External, description.Kind); Assert.NotNull(description.AuthUI); Assert.Equal(msftAuther.GetUI().AccountNoun, description.AuthUI.AccountNoun); }
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(); }
public Fakes() { User = new User("testUser") { Key = 42, EmailAddress = "*****@*****.**", Credentials = new List <Credential> { CredentialBuilder.CreatePbkdf2Password(Password), CredentialBuilder.CreateV1ApiKey(Guid.Parse("519e180e-335c-491a-ac26-e83c4bd31d65"), ExpirationForApiKeyV1) } }; ShaUser = new User("testShaUser") { Key = 42, EmailAddress = "*****@*****.**", Credentials = new List <Credential> { CredentialBuilder.CreateSha1Password(Password), CredentialBuilder.CreateV1ApiKey(Guid.Parse("b9704a41-4107-4cd2-bcfa-70d84e021ab2"), ExpirationForApiKeyV1) } }; Admin = new User("testAdmin") { Key = 43, EmailAddress = "*****@*****.**", Credentials = new List <Credential> { CredentialBuilder.CreatePbkdf2Password(Password) }, Roles = new List <Role> { new Role { Name = Constants.AdminRoleName } } }; Owner = new User("testPackageOwner") { Key = 44, Credentials = new List <Credential> { CredentialBuilder.CreatePbkdf2Password(Password) }, EmailAddress = "*****@*****.**" //package owners need confirmed email addresses, obviously. }; Package = new PackageRegistration { Id = "FakePackage", Owners = new List <User> { Owner }, Packages = new List <Package> { new Package { Version = "1.0" }, new Package { Version = "2.0" } } }; }
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 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 = new 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 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 = new 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 <ActionResult> CreateUser(NewUserModel model) { if (!ModelState.IsValid) { return(View("New", model)); } var foundUser = UserService.GetUser(model.Username, model.EmailAddress); if (foundUser != null) { ModelState.AddModelError("Username", "A user with this username or email address is already registered."); return(View("New", model)); } if (model.Password != model.PasswordConfirmation) { ModelState.AddModelError("Password", "Passwords did not match."); return(View("New", model)); } AuthenticatedUser user; try { user = await AuthService.Register(model.Username, model.EmailAddress, model.FullName, CredentialBuilder.CreatePbkdf2Password(model.Password)); } catch (EntityException ex) { ModelState.AddModelError("Register", ex.Message); return(View("New", model)); } return(SafeRedirect(Url.AdminUsers())); }
public async Task GivenNoLinkAndEmailClaim_ItDisplaysLogOnViewWithEmailPrefilled() { // Arrange var cred = new 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); }
public void GivenAPasswordCredential_ItDescribesItCorrectly() { // Arrange var cred = new CredentialBuilder().CreatePasswordCredential("wibblejab"); var authService = Get<AuthenticationService>(); // Act var description = authService.DescribeCredential(cred); // Assert Assert.Equal(cred.Type, description.Type); Assert.Equal(Strings.CredentialType_Password, description.TypeCaption); Assert.Null(description.Identity); Assert.True(string.IsNullOrEmpty(description.Value)); Assert.Equal(CredentialKind.Password, description.Kind); Assert.Null(description.AuthUI); }
private TestableApiKeyAuthenticationHandler() { Logger = (MockLogger = new Mock <ILogger>()).Object; Auth = (MockAuth = new Mock <AuthenticationService>()).Object; CredentialBuilder = new CredentialBuilder(); }
public Fakes() { _users = Get <User>(); _packageRegistrations = Get <PackageRegistration>(); var key = 39; var credentialBuilder = new CredentialBuilder(); User = new User("testUser") { Key = key++, EmailAddress = "*****@*****.**", Credentials = new List <Credential> { credentialBuilder.CreatePasswordCredential(Password), TestCredentialHelper.CreateV1ApiKey(Guid.Parse("669e180e-335c-491a-ac26-e83c4bd31d65"), ExpirationForApiKeyV1), TestCredentialHelper.CreateV2ApiKey(Guid.Parse("779e180e-335c-491a-ac26-e83c4bd31d87"), ExpirationForApiKeyV1).WithDefaultScopes(), TestCredentialHelper.CreateV4ApiKey(null, out string apiKeyV4PlaintextValue).WithDefaultScopes(), TestCredentialHelper.CreateV2VerificationApiKey(Guid.Parse("b0c51551-823f-4701-8496-43980b4b3913")), TestCredentialHelper.CreateExternalCredential("abc") } }; ApiKeyV4PlaintextValue = apiKeyV4PlaintextValue; Organization = new Organization("testOrganization") { Key = key++, EmailAddress = "*****@*****.**", // invalid credentials for testing authentication constraints Credentials = new List <Credential> { credentialBuilder.CreatePasswordCredential(Password) } }; CreateOrganizationUsers(ref key, credentialBuilder, "", out var organization, out var organizationAdmin, out var organizationCollaborator); Organization = organization; OrganizationAdmin = organizationAdmin; OrganizationCollaborator = organizationCollaborator; CreateOrganizationUsers(ref key, credentialBuilder, "Owner", out var organizationOwner, out var organizationAdminOwner, out var organizationCollaboratorOwner); OrganizationOwner = organizationOwner; OrganizationOwnerAdmin = organizationAdminOwner; OrganizationOwnerCollaborator = organizationCollaboratorOwner; Pbkdf2User = new User("testPbkdf2User") { Key = key++, EmailAddress = "*****@*****.**", Credentials = new List <Credential> { TestCredentialHelper.CreatePbkdf2Password(Password), TestCredentialHelper.CreateV1ApiKey(Guid.Parse("519e180e-335c-491a-ac26-e83c4bd31d65"), ExpirationForApiKeyV1) } }; ShaUser = new User("testShaUser") { Key = key++, EmailAddress = "*****@*****.**", Credentials = new List <Credential> { TestCredentialHelper.CreateSha1Password(Password), TestCredentialHelper.CreateV1ApiKey(Guid.Parse("b9704a41-4107-4cd2-bcfa-70d84e021ab2"), ExpirationForApiKeyV1) } }; Admin = new User("testAdmin") { Key = key++, EmailAddress = "*****@*****.**", Credentials = new List <Credential> { TestCredentialHelper.CreatePbkdf2Password(Password) }, Roles = new List <Role> { new Role { Name = Constants.AdminRoleName } } }; Owner = new User("testPackageOwner") { Key = key++, Credentials = new List <Credential> { TestCredentialHelper.CreatePbkdf2Password(Password) }, EmailAddress = "*****@*****.**" //package owners need confirmed email addresses, obviously. }; Package = new PackageRegistration { Id = "FakePackage", Owners = new List <User> { Owner, OrganizationOwner }, }; Package.Packages = new List <Package> { new Package { Version = "1.0", PackageRegistration = Package }, new Package { Version = "2.0", PackageRegistration = Package } }; }
public async Task GivenAssociatedLocalAdminUser_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 fakes = Get <Fakes>(); GetMock <AuthenticationService>(); // Force a mock to be created var controller = GetController <AuthenticationController>(); var cred = new 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.CreateSessionAsync(controller.OwinContext, authUser)) .Returns(Task.FromResult(0)) .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 virtual Task <ActionResult> RegisterUser(LogOnViewModel model, string returnUrl, bool linkingAccount) { // I think it should be obvious why we don't want the current URL to be the return URL here ;) ViewData[Constants.ReturnUrlViewDataKey] = returnUrl; if (Request.IsAuthenticated) { TempData["Message"] = Strings.AlreadyLoggedIn; return(SafeRedirect(returnUrl)); } if (linkingAccount) { ModelState.Remove("Register.Password"); } if (!ModelState.IsValid) { return(LogOnView(model)); } AuthenticatedUser user; try { if (linkingAccount) { var result = await AuthService.ReadExternalLoginCredential(OwinContext); if (result.ExternalIdentity == null) { return(ExternalLinkExpired()); } user = await AuthService.Register( model.Register.Username, model.Register.EmailAddress, result.Credential); } else { user = await AuthService.Register( model.Register.Username, model.Register.EmailAddress, CredentialBuilder.CreatePbkdf2Password(model.Register.Password)); } } catch (EntityException ex) { ModelState.AddModelError("Register", ex.Message); return(LogOnView(model)); } // Send a new account email MessageService.SendNewAccountEmail( new MailAddress(user.User.UnconfirmedEmailAddress, user.User.Username), Url.ConfirmationUrl( "Confirm", "Users", user.User.Username, user.User.EmailConfirmationToken)); // We're logging in! AuthService.CreateSession(OwinContext, user.User); return(RedirectFromRegister(returnUrl)); }
public Fakes() { var credentialBuilder = new CredentialBuilder(); User = new User("testUser") { Key = 40, EmailAddress = "*****@*****.**", Credentials = new List <Credential> { credentialBuilder.CreatePasswordCredential(Password), TestCredentialHelper.CreateV1ApiKey(Guid.Parse("669e180e-335c-491a-ac26-e83c4bd31d65"), ExpirationForApiKeyV1), TestCredentialHelper.CreateV2ApiKey(Guid.Parse("779e180e-335c-491a-ac26-e83c4bd31d87"), ExpirationForApiKeyV1), TestCredentialHelper.CreateV2VerificationApiKey(Guid.Parse("b0c51551-823f-4701-8496-43980b4b3913")), TestCredentialHelper.CreateExternalCredential("abc") } }; Organization = new Organization("testOrganization") { Key = 41, EmailAddress = "*****@*****.**", // invalid credentials for testing authentication constraints Credentials = new List <Credential> { credentialBuilder.CreatePasswordCredential(Password) } }; var membership = new Membership { Organization = Organization, Member = User, IsAdmin = true }; User.Organizations.Add(membership); Organization.Members.Add(membership); Pbkdf2User = new User("testPbkdf2User") { Key = 41, EmailAddress = "*****@*****.**", Credentials = new List <Credential> { TestCredentialHelper.CreatePbkdf2Password(Password), TestCredentialHelper.CreateV1ApiKey(Guid.Parse("519e180e-335c-491a-ac26-e83c4bd31d65"), ExpirationForApiKeyV1) } }; ShaUser = new User("testShaUser") { Key = 42, EmailAddress = "*****@*****.**", Credentials = new List <Credential> { TestCredentialHelper.CreateSha1Password(Password), TestCredentialHelper.CreateV1ApiKey(Guid.Parse("b9704a41-4107-4cd2-bcfa-70d84e021ab2"), ExpirationForApiKeyV1) } }; Admin = new User("testAdmin") { Key = 43, EmailAddress = "*****@*****.**", Credentials = new List <Credential> { TestCredentialHelper.CreatePbkdf2Password(Password) }, Roles = new List <Role> { new Role { Name = Constants.AdminRoleName } } }; Owner = new User("testPackageOwner") { Key = 44, Credentials = new List <Credential> { TestCredentialHelper.CreatePbkdf2Password(Password) }, EmailAddress = "*****@*****.**" //package owners need confirmed email addresses, obviously. }; Package = new PackageRegistration { Id = "FakePackage", Owners = new List <User> { Owner }, }; Package.Packages = new List <Package> { new Package { Version = "1.0", PackageRegistration = Package }, new Package { Version = "2.0", PackageRegistration = Package } }; }
public async Task GivenPasswordCredential_ItThrowsArgumentException() { // Arrange var cred = new CredentialBuilder().CreatePasswordCredential("bogus"); // Act var ex = await Assert.ThrowsAsync<ArgumentException>(async () => await _authenticationService.Authenticate(cred)); // Assert Assert.Equal( Strings.PasswordCredentialsCannotBeUsedHere + Environment.NewLine + "Parameter name: credential", ex.Message); Assert.Equal("credential", ex.ParamName); }
public async Task GivenAdminLogsInWithExternalIdentity_ItChallengesWhenNotUsingRequiredExternalProvider(string providerUsedForLogin, bool shouldChallenge) { // Arrange var enforcedProvider = "AzureActiveDirectory"; var configurationService = GetConfigurationService(); configurationService.Current.ConfirmEmailAddresses = false; configurationService.Current.EnforcedAuthProviderForAdmin = enforcedProvider; var externalCred = new 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 GivenMatchingApiKey_ItReturnsTicketWithUserNameAndRoles() { // Arrange var user = new User { Username = "******", EmailAddress = "*****@*****.**" }; var handler = await TestableApiKeyAuthenticationHandler.CreateAsync(new ApiKeyAuthenticationOptions()); var apiKeyCredential = new CredentialBuilder().CreateApiKey(Fakes.ExpirationForApiKeyV1); handler.OwinContext.Request.Headers.Set( Constants.ApiKeyHeaderName, apiKeyCredential.Value.ToLowerInvariant()); handler.MockAuth.SetupAuth(apiKeyCredential, user); // Act var ticket = await handler.InvokeAuthenticateCoreAsync(); // Assert Assert.NotNull(ticket); Assert.Equal(apiKeyCredential.Value.ToLower(), ticket.Identity.GetClaimOrDefault(NuGetClaims.ApiKey)); }