protected override async Task <AuthenticateResult> HandleAuthenticateAsync() { if (!Request.Headers.ContainsKey("Authorization")) { //Authorization header not in request return(AuthenticateResult.NoResult()); } if (!AuthenticationHeaderValue.TryParse(Request.Headers["Authorization"], out AuthenticationHeaderValue headerValue)) { //Invalid Authorization header return(AuthenticateResult.NoResult()); } if (!"Basic".Equals(headerValue.Scheme, StringComparison.OrdinalIgnoreCase)) { //Not Basic authentication header return(AuthenticateResult.NoResult()); } byte[] headerValueBytes = Convert.FromBase64String(headerValue.Parameter); string userAndPassword = Encoding.UTF8.GetString(headerValueBytes); string[] parts = userAndPassword.Split(':'); if (parts.Length != 2) { return(AuthenticateResult.Fail("Invalid Basic authentication header")); } string user = parts[0]; string password = parts[1]; // static password as a secret for backend protection, username is dynamic - the currently authenticated user bool isValidUser = password == userContext.SecretKey; if (!isValidUser) { return(AuthenticateResult.Fail("Invalid username or password")); } var claims = new List <Claim>(); // we even make access here before we have a user, so we skip the user specific part in case it's just a logon attempt if (!String.IsNullOrEmpty(user)) { claims.Add(new Claim(ClaimTypes.Name, user)); var claimsHeader = Request.Headers["X-User-Claims"]; if (!string.IsNullOrEmpty(claimsHeader)) { var userClaims = claimsHeader .SelectMany(c => c.Split(',')) .Select(c => Encoding.ASCII.GetString(Convert.FromBase64String(c.Trim()))) .Select(c => { var claimParts = c.Split('|'); return(new Claim(claimParts[0], claimParts[1])); }); claims.AddRange(userClaims); } } var identity = new ClaimsIdentity(claims, Scheme.Name); // this keeps the user's identity for business logic purpose userContext.SetUserIdentity(identity); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); return(await Task.FromResult(AuthenticateResult.Success(ticket))); }