/// <summary>
        /// Gets whether this provider has a standard payload: <see cref="CreatePayload"/> can be called.
        /// </summary>
        /// <param name="this">This provider.</param>
        /// <returns>True if this provider has a payload.</returns>
        public static bool HasPayload(this IGenericAuthenticationProvider @this)
        {
            var t  = @this.GetType().GetTypeInfo();
            var eI = t.ImplementedInterfaces
                     .FirstOrDefault(iT => iT.GetTypeInfo().IsGenericType&& iT.GetGenericTypeDefinition() == typeof(IGenericAuthenticationProvider <>));

            return(eI != null);
        }
        /// <summary>
        /// Creates an empty payload object. <see cref="HasPayload"/> must be true otherwise
        /// an <see cref="InvalidOperationException"/> is thrown.
        /// </summary>
        /// <param name="this">This provider.</param>
        /// <returns>An empty payload object.</returns>
        public static object CreatePayload(this IGenericAuthenticationProvider @this)
        {
            var t  = @this.GetType().GetTypeInfo();
            var eI = t.ImplementedInterfaces
                     .FirstOrDefault(iT => iT.GetTypeInfo().IsGenericType&& iT.GetGenericTypeDefinition() == typeof(IGenericAuthenticationProvider <>));

            if (eI == null)
            {
                throw new InvalidOperationException();
            }
            return(eI.GetMethod(nameof(IGenericAuthenticationProvider <object> .CreatePayload))
                   .Invoke(@this, Array.Empty <object>()));
        }
Ejemplo n.º 3
0
        static public void StandardTestForGenericAuthenticationProvider(
            Package auth,
            string schemeOrProviderName,
            Func <int, string, object> payloadForCreateOrUpdate,
            Func <int, string, object> payloadForLogin,
            Func <int, string, object> payloadForLoginFail
            )
        {
            var user = TestHelper.StObjMap.Default.Obtain <Actor.UserTable>();
            IGenericAuthenticationProvider g = auth.FindProvider(schemeOrProviderName);

            using (var ctx = new SqlStandardCallContext())
            {
                string userName = Guid.NewGuid().ToString();
                int    userId   = user.CreateUser(ctx, 1, userName);
                using (TestHelper.Monitor.OpenInfo($"StandardTest for generic {schemeOrProviderName} with userId:{userId} and userName:{userName}."))
                {
                    IUserAuthInfo info = auth.ReadUserAuthInfo(ctx, 1, userId);
                    info.UserId.Should().Be(userId);
                    info.UserName.Should().Be(userName);
                    info.Schemes.Should().BeEmpty();

                    using (TestHelper.Monitor.OpenInfo("CreateOrUpdateUser without login"))
                    {
                        g.CreateOrUpdateUser(ctx, 1, userId, payloadForCreateOrUpdate(userId, userName)).OperationResult.Should().Be(UCResult.Created);
                        info = auth.ReadUserAuthInfo(ctx, 1, userId);
                        info.Schemes.Count.Should().Be(0, "Still no scheme since we did not use WithActualLogin.");

                        g.LoginUser(ctx, payloadForLogin(userId, userName), actualLogin: false).UserId.Should().Be(userId);
                        info = auth.ReadUserAuthInfo(ctx, 1, userId);
                        info.Schemes.Should().BeEmpty("Still no scheme since we challenge login but not use WithActualLogin.");

                        g.LoginUser(ctx, payloadForLogin(userId, userName)).UserId.Should().Be(userId);
                        info = auth.ReadUserAuthInfo(ctx, 1, userId);
                        info.Schemes.Count.Should().Be(1);
                        info.Schemes[0].Name.Should().StartWith(g.ProviderName);
                        info.Schemes[0].Name.Should().BeEquivalentTo(schemeOrProviderName);
                        info.Schemes[0].LastUsed.Should().BeCloseTo(DateTime.UtcNow, 1000);

                        g.DestroyUser(ctx, 1, userId);
                        info = auth.ReadUserAuthInfo(ctx, 1, userId);
                        info.Schemes.Should().BeEmpty();
                    }
                    using (TestHelper.Monitor.OpenInfo("CreateOrUpdateUser WithActualLogin"))
                    {
                        info.UserId.Should().Be(userId);
                        info.UserName.Should().Be(userName);
                        info.Schemes.Should().BeEmpty();

                        var result = g.CreateOrUpdateUser(ctx, 1, userId, payloadForCreateOrUpdate(userId, userName), UCLMode.CreateOnly | UCLMode.WithActualLogin);
                        result.OperationResult.Should().Be(UCResult.Created);
                        result.LoginResult.UserId.Should().Be(userId);
                        info = auth.ReadUserAuthInfo(ctx, 1, userId);
                        info.Schemes.Should().HaveCount(1);
                        info.Schemes[0].Name.Should().StartWith(g.ProviderName);
                        info.Schemes[0].Name.Should().BeEquivalentTo(schemeOrProviderName);
                        info.Schemes[0].LastUsed.Should().BeCloseTo(DateTime.UtcNow, 1000);

                        g.LoginUser(ctx, payloadForLoginFail(userId, userName)).UserId.Should().Be(0);

                        g.DestroyUser(ctx, 1, userId);
                        info = auth.ReadUserAuthInfo(ctx, 1, userId);
                        info.Schemes.Should().BeEmpty();
                    }
                    using (TestHelper.Monitor.OpenInfo("Login for an unregistered user."))
                    {
                        info.UserId.Should().Be(userId);
                        info.UserName.Should().Be(userName);
                        info.Schemes.Should().BeEmpty();

                        var result = g.LoginUser(ctx, payloadForLogin(userId, userName));
                        result.IsSuccess.Should().BeFalse();
                        result.UserId.Should().Be(0);
                        result.FailureCode.Should().Be((int)KnownLoginFailureCode.UnregisteredUser);
                        result.FailureReason.Should().Be("Unregistered user.");
                        info = auth.ReadUserAuthInfo(ctx, 1, userId);
                        info.Schemes.Should().BeEmpty();

                        g.DestroyUser(ctx, 1, userId);
                        info = auth.ReadUserAuthInfo(ctx, 1, userId);
                        info.Schemes.Should().BeEmpty();
                    }
                    using (TestHelper.Monitor.OpenInfo("Invalid payload MUST throw an ArgumentException."))
                    {
                        g.Invoking(sut => sut.CreateOrUpdateUser(ctx, 1, userId, DBNull.Value)).Should().Throw <ArgumentException>();
                        g.Invoking(sut => sut.LoginUser(ctx, DBNull.Value)).Should().Throw <ArgumentException>();
                    }
                }
                user.DestroyUser(ctx, 1, userId);
            }
        }
Ejemplo n.º 4
0
        static public async Task StandardTestForGenericAuthenticationProviderAsync(
            Package auth,
            string schemeOrProviderName,
            Func <int, string, object> payloadForCreateOrUpdate,
            Func <int, string, object> payloadForLogin,
            Func <int, string, object> payloadForLoginFail
            )
        {
            var user = TestHelper.StObjMap.Default.Obtain <Actor.UserTable>();
            IGenericAuthenticationProvider g = auth.FindProvider(schemeOrProviderName);

            using (var ctx = new SqlStandardCallContext())
            {
                string userName = Guid.NewGuid().ToString();
                int    userId   = await user.CreateUserAsync(ctx, 1, userName);

                using (TestHelper.Monitor.OpenInfo($"StandardTestAsync for generic {schemeOrProviderName} with userId:{userId} and userName:{userName}."))
                {
                    IUserAuthInfo info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId);

                    info.UserId.Should().Be(userId);
                    info.UserName.Should().Be(userName);
                    info.Schemes.Should().BeEmpty();

                    using (TestHelper.Monitor.OpenInfo("CreateOrUpdateUser without login."))
                    {
                        (await g.CreateOrUpdateUserAsync(ctx, 1, userId, payloadForCreateOrUpdate(userId, userName))).OperationResult.Should().Be(UCResult.Created);
                        info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId);

                        info.Schemes.Should().BeEmpty("Still no scheme since we did not use WithLogin.");

                        (await g.LoginUserAsync(ctx, payloadForLogin(userId, userName), actualLogin: false)).UserId.Should().Be(userId);
                        info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId);

                        info.Schemes.Should().BeEmpty("Still no scheme since we challenge login but not use WithLogin.");

                        (await g.LoginUserAsync(ctx, payloadForLogin(userId, userName))).UserId.Should().Be(userId);
                        info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId);

                        info.Schemes.Should().HaveCount(1);
                        info.Schemes[0].Name.Should().StartWith(g.ProviderName);
                        info.Schemes[0].Name.Should().BeEquivalentTo(schemeOrProviderName);
                        info.Schemes[0].LastUsed.Should().BeCloseTo(DateTime.UtcNow, 1000);

                        await g.DestroyUserAsync(ctx, 1, userId);

                        info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId);

                        info.Schemes.Should().BeEmpty();
                    }
                    using (TestHelper.Monitor.OpenInfo("CreateOrUpdateUser WithActualLogin."))
                    {
                        info.UserId.Should().Be(userId);
                        info.UserName.Should().Be(userName);
                        info.Schemes.Should().BeEmpty();

                        var result = await g.CreateOrUpdateUserAsync(ctx, 1, userId, payloadForCreateOrUpdate( userId, userName ), UCLMode.CreateOnly | UCLMode.WithActualLogin);

                        result.OperationResult.Should().Be(UCResult.Created);
                        result.LoginResult.UserId.Should().Be(userId);
                        info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId);

                        info.Schemes.Count.Should().Be(1);
                        info.Schemes[0].Name.Should().StartWith(g.ProviderName);
                        info.Schemes[0].Name.Should().BeEquivalentTo(schemeOrProviderName);
                        info.Schemes[0].LastUsed.Should().BeCloseTo(DateTime.UtcNow, 1000);

                        (await g.LoginUserAsync(ctx, payloadForLoginFail(userId, userName))).UserId.Should().Be(0);

                        await g.DestroyUserAsync(ctx, 1, userId);

                        info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId);

                        info.Schemes.Should().BeEmpty();
                    }
                    using (TestHelper.Monitor.OpenInfo("Login for an unregistered user."))
                    {
                        info.UserId.Should().Be(userId);
                        info.UserName.Should().Be(userName);
                        info.Schemes.Should().BeEmpty();

                        var result = await g.LoginUserAsync(ctx, payloadForLogin( userId, userName ));

                        result.IsSuccess.Should().BeFalse();
                        result.UserId.Should().Be(0);
                        result.FailureCode.Should().Be((int)KnownLoginFailureCode.UnregisteredUser);
                        result.FailureReason.Should().Be("Unregistered user.");
                        info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId);

                        info.Schemes.Should().BeEmpty();

                        await g.DestroyUserAsync(ctx, 1, userId);

                        info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId);

                        info.Schemes.Should().BeEmpty();
                    }
                    using (TestHelper.Monitor.OpenInfo("Invalid payload MUST throw an ArgumentException."))
                    {
                        g.Awaiting(sut => sut.CreateOrUpdateUserAsync(ctx, 1, userId, DBNull.Value)).Should().Throw <ArgumentException>();
                        g.Awaiting(sut => sut.LoginUserAsync(ctx, DBNull.Value)).Should().Throw <ArgumentException>();
                    }
                    using (TestHelper.Monitor.OpenInfo("Injecting disabled user in sAuthUserOnLogin."))
                        using (auth.Database.TemporaryTransform(@"
                            create transformer on CK.sAuthUserOnLogin
                            as
                            begin
                                inject ""set @FailureCode = 6; -- GloballyDisabledUser"" into ""CheckLoginFailure"";
                            end
                        "))
                        {
                            UCLResult result = await g.CreateOrUpdateUserAsync(ctx, 1, userId, payloadForCreateOrUpdate( userId, userName ), UCLMode.CreateOnly | UCLMode.WithActualLogin);

                            result.OperationResult.Should().Be(UCResult.Created);
                            result.LoginResult.UserId.Should().Be(0);
                            result.LoginResult.IsSuccess.Should().BeFalse();
                            result.LoginResult.FailureCode.Should().Be((int)KnownLoginFailureCode.GloballyDisabledUser);
                            LoginResult login = await g.LoginUserAsync(ctx, payloadForLogin( userId, userName ));

                            login.IsSuccess.Should().BeFalse();
                            login.UserId.Should().Be(0);
                            login.FailureCode.Should().Be((int)KnownLoginFailureCode.GloballyDisabledUser);
                            login = await g.LoginUserAsync(ctx, payloadForLogin( userId, userName ), actualLogin : false);

                            login.IsSuccess.Should().BeFalse();
                            login.UserId.Should().Be(0);
                            login.FailureCode.Should().Be((int)KnownLoginFailureCode.GloballyDisabledUser);
                        }
                }
                await user.DestroyUserAsync(ctx, 1, userId);
            }
        }