Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core using custom authenticationhandler with cookieauthentication

I'm trying to create my own AuthenticationHandler and use with cookie authentication:

services.AddAuthentication(options =>
  {
  options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
  options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
  options.DefaultChallengeScheme = MyAuth.Scheme;
  })
  .AddCookie()
  .AddScheme<MyAuthenticationOptions, MyAuthenticationHandler>(MyAuth.Scheme, "My auth scheme", options => { });

.

public MyAuthenticationHandler(...) : base(...) {}

    protected override Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        throw new NotImplementedException();  
    }    

    protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
    {                     
        var myUser = await DoAuth();

        if (!myUser.IsAuthenticated)
        {
            if (Context.Request.Query.ContainsKey("isRedirectedFromSSO"))
            {
                Context.Response.Redirect("/unauthorized");
                return;
            }
            else
            {
                Context.Response.Redirect("url to sso");
                return;
            }              
        }    

        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, user.Username),            
        };

        var identity = new ClaimsIdentity(claims, MyAuth.Scheme);
        var claimsPrincipal = new ClaimsPrincipal(identity);

        var authProperties = new AuthenticationProperties {};

        await Context.SignInAsync(
            CookieAuthenticationDefaults.AuthenticationScheme,
            claimsPrincipal,
            authProperties);

        Context.Response.Redirect(Request.GetEncodedUrl());
    }
}
  1. If there is a valid auth cookie, auth using that
  2. If there is not a valid auth cookie, challenge using my auth and create an auth cookie if successful

This works in practice, but I find it a little weird I'm doing the actual authentication in HandleChallenge and redirecting if it fails. It also seems odd to me to be calling one AuthenticationHandler (cookie) from another (MyAuthenticationHandler).

How can I set this up correctly so that I'm doing the implementation in HandleAuthenticate instead? With my current implementation that method is never actually called.

Also, is it ok to call one authentication handler from another?

P.S. I have looked at several other posts and articles (including this, this and this), but I have not been able to find the answers to my questions from looking at them. Any help would be appreciated.

like image 468
severin Avatar asked May 16 '18 12:05

severin


1 Answers

I think what you're after may be solved with some new pieces in ASP.NET Core 2.1

<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.1.0-rc1-final" />

Here's a sample of how to "select" auth schemes based on httpcontext data:

builder.AddPolicyScheme("scheme", "scheme", opts =>
{
    opts.ForwardDefaultSelector = ctx =>
    {
        if (ctx.Request.Query.ContainsKey("isRedirectedFromSSO"))
        {               
            return null; // or ctx.ForbidAsync(), not sure here.
        }

        return OpenIdConnectDefaults.AuthenticationScheme; // or your own sso scheme, whatever it may be here.
    };
})
.AddCookie()
.AddOpenIdConnect();

Have a look in this GitHub thread.

like image 114
John Korsnes Avatar answered Nov 07 '22 12:11

John Korsnes