Authenticate method returns null

I am having a weird issue with the authenticate service. I am calling the authenticate service manually like this.

var auth = authService.Authenticate(new Authenticate
{
    provider = CredentialsAuthProvider.Name,
    UserName = request.Username,
    Password = request.Password,
    RememberMe = false,
});

Initially, in the app host I was using the MemoryCacheClient and everything worked fine. Then I just switched it out with the Redis and I started getting a null back from the Authenticate method. However, this doesn’t happen every time which makes it difficult to troubleshoot. Sometimes it works without any issues, so the users exist. Other times it just return null. I am using SS 4.0.42.0. Any help is appreciated!

Here is my app host:
JsConfig.EmitCamelCaseNames = false;
JsConfig.IncludeNullValues = true;
JsConfig.IncludeTypeInfo = true;
var appSettings = new AppSettings();

        SetConfig(new HostConfig
        {
            DebugMode = appSettings.Get("DebugMode", false),
            EnableFeatures = Feature.All.Remove(Feature.Metadata)
        });

        //REDIS
        //container.Register<ICacheClient>(new MemoryCacheClient());
        container.Register<IRedisClientsManager>(c => new PooledRedisClientManager(appSettings.Get("RedisAddress")));
        container.Register<ICacheClient>(c => (ICacheClient)c.Resolve<IRedisClientsManager>().GetCacheClient()).ReusedWithin(Funq.ReuseScope.None);

        //Plugins
        this.Plugins.Add(new RazorFormat());
        Plugins.Add(new SessionFeature());
        Plugins.Add(new AuthFeature(() => new CustomUserSession(), new IAuthProvider[] { new CredentialsAuthProvider() }));
		
		var connStr = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
        container.Register<IDbConnectionFactory>(new OrmLiteConnectionFactory(connStr, SqlServerOrmLiteDialectProvider.Instance) { ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current) });

        //Store User Data into the referenced SqlServer database
        container.Register<IUserAuthRepository>(c => new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>())); //Use OrmLite DB Connection to persist the UserAuth and AuthProvider info

Does CustomUserSession have DataContract attributes?

Also registering Redis CacheClient can just be:

container.Register(c => c.Resolve<IRedisClientsManager>().GetCacheClient());

And you don’t need to register the SessionFeature as it’s automatically registered by AuthFeature

 //Plugins.Add(new SessionFeature());

This can be a little shorter too :slight_smile:

container.Register<IDbConnectionFactory>(
    new OrmLiteConnectionFactory(connStr, SqlServerDialect.Provider) { 
        ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current) 
    });  

You may want to call InitSchema which will create any missing RDBMS tables:

container.Resolve<IUserAuthRepository>().InitSchema();

Thanks for all the tips!

Here is what it looks like:

[DataContract]
public class CustomUserSession : AuthUserSession
{
    //CUSTOM SESSION PROPERTIES
    [DataMember]
    public Guid UserId { get; set; }
}

Calling Authenticate() can return null if what’s returned is not an AuthenticateResponse e.g. it could be a redirect HttpResult which because of the strong AuthenticateResponse Response Type will be safe casted to null.

Try instead calling the Post() API, e.g:

var response = authService.Post(new Authenticate
{
    provider = CredentialsAuthProvider.Name,
    UserName = request.Username,
    Password = request.Password,
});

FYI since you’re calling Authentication Service in-process you could take advantage of the CredentialsAuthProvider. SkipPasswordVerificationForInProcessRequests feature if you need it.

That didn’t work. I need the AuthenticateResponse object because I pull the Id from it. When I tried the Post and casting the result to AuthenticateResponse I got this error:

"Unable to cast object of type 'ServiceStack.HttpResult' to type 'ServiceStack.AuthenticateResponse"

Right, this is what it’s meant to happen you get the actual response object instead of null, if it’s not returning the AuthenticateResponse find out what it is returning, that will likely tell you what the issue is.

Since it’s a HttpResult find out what’s in it? i.e. is it a redirect HttpResult? to what?

Gothca. I am getting a 302 Found. But there is my login data in the Response property.

I then also tried logging in with an invalid password and get the 302 Found but the Response property is null. So, is it a safe assumption to only check if the the Response property is null (meaning the login info was invalid) and if there is a response then it was valid?

After some more testing I am having the same issue. When I use the MemoryCacheClient it all works and I get the Response.

container.Register<ICacheClient>(new MemoryCacheClient());

But when I comment that out and replace it with Redis, I get the null in the Response with the same 302 Found status.

container.Register<IRedisClientsManager>(c => new PooledRedisClientManager(appSettings.Get("RedisAddress")));

container.Register<ICacheClient>(c => (ICacheClient)c.Resolve<IRedisClientsManager>().GetCacheClient()).ReusedWithin(Funq.ReuseScope.None);

A 302 Found Response is a Redirect Response, what’s the actual redirect url in HttpResult.Headers["Location"] header?

{[Location, http://localhost:49686/login#s=0]}

Cool #s=... means it was successful, #f=... means it failed. It returns #s=0 if the User was already authenticated. Was the User already Authenticated? i.e. this.GetSession().IsAuthenticated?

Is the difference then just because you’re testing after restarting the AppDomain where the Memory CacheClient is always cleared so the user is not authenticated but when you’re testing with Redis the user was already authenticated previously? If so clear the Redis Cache with FLUSHALL when you restart the AppDomain so you can compare CacheClients behavior when they both start from no state.

That’s great. Thank you!