1

I'm looking for a minimal example for a custom authentication writen in C# for asp.net core 2 based on for example API keys.

Mircosoft has a pretty good documentation about doing this with cookies, however this is not what I want. Since I want to use API keys (given by http-header, GET or Cookie, ...) I never make a call to HttpContext.SignInAsync and this is maybe the issue I can't find/google my way around.

I built an simple AuthenticationHandler (based on this - since I read that custom middlewares are not the way to go anymore) which looks something like this:

internal class CustomAuthHandler : AuthenticationHandler<CustomAuthOptions>
{
    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        // parse cookies to find APIKEY
        if(Context.Request.Cookies.ContainsKey("APIKEY"))
        {
            string APIKEY = Request.Cookies["APIKEY"];
            // ... checking DB for APIKEY ...

            // creating claims
            var claims = new[]
            {
                new Claim( /* ... */ ),
                // ...
            };

            var claimsIdentity = new ClaimsIdentity(claims);
            var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
            var ticket = new AuthenticationTicket(claimsPrincipal, new AuthenticationProperties(), "Custom Scheme");
            return AuthenticateResult.Success(ticket); // this line gets called
        }

        return AuthenticateResult.NoResult();
    }
}

But when I have an API endpoint with just the [Authorize] attribute the DenyAnonymousAuthorizationRequirement denies the request cause the user is not allowed (cause IsAuthenticated == false which is readonly, all claims are shown properly)

Camilo Terevinto
  • 26,697
  • 6
  • 67
  • 99
Fritz
  • 463
  • 2
  • 13
  • Some pointers, the AuthenticationScheme drives everything, and there is an overload for SignInAsync that accepts the auth scheme - so basically if you want to roll out your own auth then look at the AuthenticationMiddleware and scourer the Security repo – Callum Linington Jul 27 '18 at 17:10
  • But when to call SignInAsync? I tried to call it in the auth handler but this has not changed the `IsAuthenticated` property – Fritz Jul 27 '18 at 17:12
  • So I've created middleware above UseMvc or anything else that listens to /signin then when that endpoint gets called I will authenticate the user via what ever means, username/password or something then call signinasync – Callum Linington Jul 27 '18 at 17:13
  • I don't use a classic login. When I try to implement `SignInAsync` from IAuthenticationSignInHandler` I don't find a way to set `IsAuthenticated` – Fritz Jul 27 '18 at 19:45
  • IsAuthenticated is set when you set a principle on the context – Callum Linington Jul 27 '18 at 19:46

1 Answers1

2

Change var claimsIdentity = new ClaimsIdentity(claims); into something like var claimsIdentity = new ClaimsIdentity(claims, "Password"); (of course, instead of "Password" use the AuthenticationType that best fits your case).

Similar question here: Why is my ClaimsIdentity IsAuthenticated always false (for web api Authorize filter)?

Mladen B.
  • 2,297
  • 2
  • 18
  • 30
  • Wow, this fixed my auth handler too. That's really quite obscure. – Ryan Apr 05 '21 at 08:28
  • I agree, perhaps the docs could be more clear on the usage.. I guess the idea is that claims can come from different sources, and you can either trust them all together or just trust particular claims from a specific source (in this case "Password" source), if you have more sources (e.g. external authentications like Auth0. Google, FB). That's probably why things didn't work until you specified the "Password" source. – Mladen B. Apr 08 '21 at 13:07