Search code examples
asp.net-core-mvcasp.net-core-webapiasp.net-identity-3openiddict

With openIdDict do we have to have 'UseIdentity()' in Startup.cs?


We have an asp.net core web app that uses OpenIdDict for authentication. I've noticed that my unauthenticated Ajax calls return a 200 and our login form in the body of the response. From what I've read this is expected behavior since OpenIdDict handles the request, then ASP.NET core handles it and returns the 200. ASP.NET core is handling it because UseIdentity() is being called in Startup.cs. All of the examples I've seen for OpenIdDict call UseIdentity(). I have 2 questions.

  1. If I don't want ASP.NET core to handle my request can I just remove UseIdentity()? I tried it and now I get a 401 instead of a 200. Is there any harm in doing this or does OpenIdDict require UseIdentity()?
  2. If I don't want to lose the ability for redirects to login for UI Views is the best/simplest/safest method of accomplishing this to override OnRedirectToLogin? Code example below:
    options.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents
    {
       OnRedirectToLogin = ctx =>
       {
           if (ctx.Request.Path.StartsWithSegments("/api") &&
               ctx.Response.StatusCode == (int) HttpStatusCode.OK)
           {
               ctx.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
           }
           else
           {
               ctx.Response.Redirect(ctx.RedirectUri);
           }
           return Task.FromResult(0);
       }
    };

Code sample source: https://devblog.dymel.pl/2016/07/07/return-401-unauthorized-from-asp-net-core-api/

Further discussion of this issue here: https://github.com/aspnet/Security/issues/804


Solution

  • Does OpenIdDict require 'UseIdentity()'?

    No, the cookies middleware registered under the hood by app.UseIdentity() are not directly used by OpenIddict, so calling this method is not required for OpenIddict to work correctly.

    That said, if you use the ASP.NET Core Identity features that rely on cookies authentication (pretty much everything in AccountController/ManageController), then yes, you have to use app.UseIdentity().

    All of the examples I've seen for OpenIdDict call 'UseIdentity'

    For a sample that doesn't use app.UseIdentity(), you can take a look at the official password flow sample or read this blog post, that shows how to use OpenIddict without ASP.NET Core Identity.

    If I don't want to lose the ability for redirects to login for UI Views is the best/simplest/safest method of accomplishing this to override OnRedirectToLogin?

    This definitely works, but I've personally opted for a safer option, that consists in using pipeline branching to exclude the cookies middleware registered by app.UseIdentity(). This not only prevents Identity from hijacking the 401 responses returned by your API, but also avoids XSRF attacks as HttpContext.User can't be populated with an identity extracted from a cookie:

    app.UseWhen(context => !context.Request.Path.StartsWithSegments("/api"), branch =>
    {
        branch.UseIdentity();
    });
    

    See https://github.com/openiddict/openiddict-samples/blob/master/samples/CodeFlow/AuthorizationServer/Startup.cs#L141-L158 for a complete sample.