Search code examples
windows-authenticationidentityserver3

Identity Server3 : Windows Authentication : AuthenticationResult always fails


I am using Thinktecture Identity Server 3 (OWIN and Katana) and have been able to make it work for resource owner flow without issues.

However, when it comes to authenticating windows users it fails although i can see while debugging that my custom UserService does validate the user and return a positive AuthenticationResult.

Has anyone experienced this in their implementation?

I shall post the code for the custom UserService here

public class ActiveDirectoryUserService : IUserService
{
    private const string Domain = "xxxxx";

    public Task PreAuthenticateAsync(PreAuthenticationContext context)
    {
        return Task.FromResult<AuthenticateResult>(null);
    }

    public Task AuthenticateLocalAsync(LocalAuthenticationContext context)
    {
        try
        {
            using (var pc = new PrincipalContext(ContextType.Domain, Domain))
            {
                if (pc.ValidateCredentials(context.UserName, context.Password))
                {
                    using (
                        var user = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, context.UserName))
                    {
                        if (user != null)
                        {
                            return
                                Task.FromResult(new AuthenticateResult(context.UserName, context.UserName, identityProvider: "windows"));
                        }
                    }
                }

                // The user name or password is incorrect
                return Task.FromResult<AuthenticateResult>(null);
            }
        }
        catch
        {
            // Server error
            return Task.FromResult<AuthenticateResult>(null);
        }
    }

    public Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
    {
        return Task.FromResult<AuthenticateResult>(null);
    }

    public Task PostAuthenticateAsync(PostAuthenticationContext context)
    {
        return Task.FromResult<AuthenticateResult>(context.AuthenticateResult);
    }

    public Task SignOutAsync(SignOutContext context)
    {
        return Task.FromResult<AuthenticateResult>(null);
    }

    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        using (var pc = new PrincipalContext(ContextType.Domain, Domain))
        {
            using (var user = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, context.Subject.Identity.Name))
            {
                if (user != null)
                {
                    var identity = new ClaimsIdentity();
                    identity.AddClaims(new[]
                    {
                        new Claim(Constants.ClaimTypes.Name, user.DisplayName),
                        new Claim(Constants.ClaimTypes.Email, user.EmailAddress)
                    });

                    if (context.RequestedClaimTypes != null)
                        return Task.FromResult(identity.Claims.Where(x => context.RequestedClaimTypes.Contains(x.Type)));

                    return Task.FromResult(identity.Claims);
                }
            }
            return Task.FromResult<IEnumerable<Claim>>(null);
        }
    }

    public Task IsActiveAsync(IsActiveContext context)
    {
        return Task.FromResult(context.IsActive);
    }
}

The response is always invalid username and password


Solution

  • return Task.FromResult(new AuthenticateResult(context.UserName, context.UserName, identityProvider: "windows"));

    is wrong. it should be:

    context.AuthenticateResult = new AuthenticateResult( context.UserName, context.UserName); return Task.FromResult(0);