Snippets

Stefan de Vogelaere ServiceStack Custom Auth Provider

Created by Stefan de Vogelaere
using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using Funq;
using ServiceStack;
using ServiceStack.Auth;
using ServiceStack.Caching;
using ServiceStack.Data;
using ServiceStack.OrmLite;

namespace Identity
{
    //VS.NET Template Info: https://servicestack.net/vs-templates/EmptyAspNet
    public class AppHost : AppHostBase
    {
        /// <summary>
        /// Base constructor requires a Name and Assembly where web service implementation is located
        /// </summary>
        public AppHost()
            : base("Identity", typeof(AppHost).Assembly) { }

        /// <summary>
        /// Application specific configuration
        /// This method should initialize any IoC resources utilized by your web service classes.
        /// </summary>
        public override void Configure(Container container)
        {
            //Store UserAuth in SQL Server
//            var dbFactory = new OrmLiteConnectionFactory(
//                AppSettings.GetString("SQL"),
//                SqlServerDialect.Provider);

            var dbFactory = new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider);


            container.Register<IDbConnectionFactory>(dbFactory);

            container.Register<IAuthRepository>(c => new OrmLiteAuthRepository(dbFactory) { UseDistinctRoleTables = true });
            container.Resolve<IAuthRepository>().InitSchema();

            //Also store User Sessions in SQL Server
            container.RegisterAs<OrmLiteCacheClient, ICacheClient>();
            container.Resolve<ICacheClient>().InitSchema();

            var privateKey = RsaUtils.CreatePrivateKeyParams(RsaKeyLengths.Bit2048);
            var privateKeyXml = privateKey.ToPrivateKeyXml();

            // just for testing, create a privateKeyXml on every instance
            Plugins.Add(new AuthFeature(() =>

                new AuthUserSession(),
                new IAuthProvider[]
                {
                    new JwtAuthProvider
                    {
                        HashAlgorithm = "RS256",
#if (DEBUG)
                        RequireSecureConnection = false,
#endif
                        PrivateKeyXml = privateKeyXml
                    },
                    new LegacyAuthProvider(),
                })
                {
                    IsValidUsernameFn = s => IsValidUsernameFn(s)
                }
                );


            Plugins.Add(new RegistrationFeature());
        }

        bool IsValidUsernameFn(string s)
        {
            // all names are ok for the moment
            return true;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using ServiceStack;
using ServiceStack.Auth;

namespace Identity
{
    public class LegacyAuthProvider : CredentialsAuthProvider
    {
        readonly List<LegacyUser> _legacyUsers = new List<LegacyUser>()
        {
            new LegacyUser() { UserName = "user1@host.com", Password = "p@55word", Id = Guid.NewGuid(), DatabaseId = Guid.NewGuid() },
            new LegacyUser() { UserName = "user2@host.com", Password = "p@55word", Id = Guid.NewGuid(), DatabaseId = Guid.NewGuid() },
            new LegacyUser() { UserName = "user3@host.com", Password = "p@55word", Id = Guid.NewGuid(), DatabaseId = Guid.NewGuid() },
            new LegacyUser() { UserName = "user4@host.com", Password = "p@55word", Id = Guid.NewGuid(), DatabaseId = Guid.NewGuid() },
        };


        public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
        {

            var defaultResult = base.TryAuthenticate(authService, userName, password);
            if (defaultResult) return true;

            var authRepository = (IUserAuthRepository)HostContext.AppHost.GetAuthRepository(authService.Request);

            var administratorFound = _legacyUsers.Where(u => u.UserName == userName && u.Password == password).ToList();
            if (administratorFound.Count == 0) return false;

            var administrator = administratorFound.First();

            IUserAuth userAuth = new UserAuth
            {
                UserName = administrator.UserName,
                Email = administrator.UserName
            };
            userAuth = authRepository.CreateUserAuth(userAuth, administrator.Password);
            AssignRoleAndPermissionsForAdmistrator(authRepository, userAuth, administrator);
            return true;
        }

        static void AssignRoleAndPermissionsForAdmistrator(IAuthRepository authRepository, IUserAuth userAuth,
            LegacyUser legacyUser)
        {
            AddRoleIfNotExists(authRepository, userAuth, "Admin");
            AddPermissionIfNotExists(authRepository, userAuth, "DBID|" + legacyUser.DatabaseId);
            AddPermissionIfNotExists(authRepository, userAuth, "legacy-administrator-id|" + legacyUser.Id);
        }

        static void AddRoleIfNotExists(IAuthRepository rep, IUserAuth user, string role)
        {
            if (!rep.GetRoles(user).Contains(role))
                rep.AssignRoles(user, roles: new[] { role });
        }

        static void AddPermissionIfNotExists(IAuthRepository rep, IUserAuth user, string perm)
        {
            if (!rep.GetPermissions(user).Contains(perm))
                rep.AssignRoles(user, permissions: new[] { perm });
        }

    }

    public class LegacyUser
    {
        public Guid Id { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public Guid DatabaseId { get; set; }

    }


}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.