Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Turn off AutomaticChallenge in asp.net mvc core 2 OpenIdConnect

I've added OpenID Authentication to my ASP.NET Core 2.0 wep app:

services.AddAuthentication(sharedOptions =>
        {
            sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
            .AddCookie()
            .AddOpenIdConnect(option =>
            {
                option.ClientId = Configuration["AzureAD:ClientId"];
                option.Authority = String.Format(Configuration["AzureAd:AadInstance"], Configuration["AzureAd:Tenant"]);
                option.SignedOutRedirectUri = Configuration["AzureAd:PostLogoutRedirectUri"];
            });

How do I turn on automatic challenge, so controller, resp action with AuthorizeAttribute will return 403 rather than redirect?

EDIT: I ended up with this:

.AddOpenIdConnect(option =>
{
    ...
    option.Events = new OpenIdConnectEvents
    {
        OnRedirectToIdentityProvider = context =>
        {
            bool isAjaxRequest = context.HttpContext.Request.Headers["x-requested-with"] == "XMLHttpRequest";
            if (isAjaxRequest)
            {
                context.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
                //context.HttpContext.Response.Headers["Location"] = ???request.RedirectUrl;
                context.HandleResponse();
            }
            return Task.CompletedTask;
        }
    };
});

Although I don't want to redirect Ajax request (because why?), I would like to pass the redirect url to the client. How to get the RedirectURL?

like image 301
Liero Avatar asked Sep 14 '17 15:09

Liero


1 Answers

The best solution I've been able to come with so far is:

services.AddAuthentication(sharedOptions =>
{
    sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
  .AddCookie(options =>
  {
      options.Events.OnRedirectToAccessDenied = DontRedirectAjaxOrApiRequestToForbidden;
  })
  .AddOpenIdConnect(options =>
  {
      ...
      options.Events.OnRedirectToIdentityProvider = DontRedirectAjaxRequestToOpenIdProvider;
  });


/// <summary>
/// Unauthenticated ajax or API request returns 403 rather than Redirect to forbidden page
/// </summary>
private static Task DontRedirectAjaxOrApiRequestToForbidden(RedirectContext<CookieAuthenticationOptions> ctx)
{
    bool isAjaxRequest = ctx.HttpContext.Request.Headers["x-requested-with"] == "XMLHttpRequest";
    if (isAjaxRequest || (ctx.Request.Path.StartsWithSegments("/api")))
    {
        ctx.Response.StatusCode = 403;
    }
    else
    {
        ctx.Response.Redirect(ctx.RedirectUri);
    }
    return Task.CompletedTask;
}

/// <summary>
/// Unauthenticated ajax request returns 401 rather than Redirect
/// </summary>
private static Task DontRedirectAjaxRequestToOpenIdProvider(RedirectContext redirectContext)
{
    bool isAjaxRequest = redirectContext.HttpContext.Request.Headers["x-requested-with"] == "XMLHttpRequest";
    if (isAjaxRequest)
    {
        redirectContext.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
        redirectContext.HttpContext.Response.Headers["Location"] = CookieAuthenticationDefaults.LoginPath.Value;
        redirectContext.HandleResponse();
    }
    return Task.CompletedTask;
}
like image 75
Liero Avatar answered Sep 30 '22 04:09

Liero