Preface
We just upgraded our license from 4.0.33 to 4.5.12 and this seems to be the only problem I’m encountering. The documentation hasn’t seemed to change much on doing custom authentication. When looking at this part of the documentation my code looks like it should be able to stay much the same.
The Problem
It seems that when using a CustomCredentialProvider inheriting from CredentialsAuthProvider, the session information doesn’t pass the test for the AuthenticateAttribute to show as authenticated and kicks back a 401 even though I’m logged in.
The Code
Here’s the code for CustomCredentialsAuthProvider.cs
public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
private readonly IDbConnectionFactory _connectionFactory;
private readonly LogProvider _logger;
public CustomCredentialsAuthProvider(IDbConnectionFactory connectionFactory,
IAppSettings appSettings) : base(appSettings)
{
_connectionFactory = connectionFactory;
_logger = new LogProvider(_connectionFactory.OpenDbConnection());
}
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
userName.ThrowIfNullOrEmpty();
password.ThrowIfNullOrEmpty();
using (var db = _connectionFactory.Open())
{
//Custom authentication logic goes here
var user = db.FirstOrDefault<DashboardUser>(u => u.UserName == userName && u.Active);
var success = user != null && BCrypt.Net.BCrypt.Verify(password, user.Password);
if (!success)
if (user != null)
_logger.AddLogMessage(user.Id, user.UserName, user.ReferenceLocationId,
Tokens.LoggingEvent.Login, "Unsuccessful login attempt.");
else
_logger.AddLogMessage(0, userName, 0, Tokens.LoggingEvent.Login,
string.Format("Unsuccessful login attempt with UserName: {0}", userName));
return success;
}
}
public override IHttpResult OnAuthenticated(IServiceBase authService, IAuthSession session, IAuthTokens tokens,
Dictionary<string, string> authInfo)
{
using (var db = _connectionFactory.Open())
{
//Fill the IAuthSession with data
var user = db.FirstOrDefault<DashboardUser>(u => u.UserName == session.UserAuthName);
var userSession = (CustomUserSession) session;
var roles = userSession.Roles ?? (userSession.Roles = new List<string>());
var permissions = userSession.Permissions ?? (userSession.Permissions = new List<string>());
session.PopulateWithNonDefaultValues(user);
if (user.CanManageUsers) permissions.Add(Tokens.Permissions.CanManageUsers);
//Important! Save the session data.
authService.SaveSession(session, SessionExpiry);
//log login
_logger.AddLogMessage(userSession, Tokens.LoggingEvent.Login, "Successful login.");
}
return null;
}
}
And here’s the code registering it in my AppHost.cs
private void ConfigureAuth(Container container)
{
container.Register<IAppSettings>(new AppSettings());
container.RegisterAutoWired<CustomCredentialsAuthProvider>();
//Default route: /auth/{provider}
Plugins.Add(new AuthFeature(() => new CustomUserSession(),
new IAuthProvider[] {container.Resolve<CustomCredentialsAuthProvider>()}));
//Default route: /register
//Plugins.Add(new RegistrationFeature());
}
This is the method I’m trying to call in my Services
[Authenticate]
public ResponseStatus Any(RegisterComputer request)
{
var locationId = UserSession.ReferenceLocationId;
var location = Db.First<Location>(x => x.RefLocationID == locationId);
Cache.Set(Tokens.CacheItems.LocationCacheKey, location, TimeSpan.FromHours(1));
if (UserSession.CanManageUsers && //they are admin
DateTime.UtcNow <= location.ComputerRegistrationExpiration)
{
Logger.AddLogMessage(UserSession, Tokens.LoggingEvent.ComputerRegister, "Computer registered.");
Response.SetCookie(Tokens.Cookies.ComputerRegistrationKey, location.ComputerRegistrationKey.ToString(),
DateTime.MaxValue);
}
return new ResponseStatus();
}
Conclusion
This all looks fine, but doesn’t seem to work anymore. It will authenticate me using the provider but the first call to anything with the AuthenticateAttribute will always result in 401. I tried using the debug symbols to see if I could step into the AuthenticateAttribute but can’t seem to get that to work. Any guidance would be appreciated.