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);
            }
예제 #2
0
            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();
            }
예제 #7
0
        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));
            }
예제 #10
0
        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();
            }