Geir Sagberg
Geir Sagberg

Reputation: 9821

How can I replace HttpContext.User in ASP.NET Core after Authorization?

I have a custom user class MyPrincipal with some custom properties, with which I want to replace the authenticated ClaimsPrincipal, e.g. HttpContext.User

I have added a custom middleware:

public class MyMiddleware {
  private readonly RequestDelegate next;

  public MyMiddleware(RequestDelegate next) {
    this.next = next;
  }

  public async Task Invoke(HttpContext context) {
    if (context.User.IsAuthenticated) {
      context.User = new MyPrincipal(context.User);
    }
    await next(context);
  }
}

I have registered the middleware to run after authentication, but before MVC in Startup.cs:

public void Configure(IApplicationBuilder app) {
  app.UseAuthentication();
  app.UseMiddleware<MyMiddleware()>;
  app.UseMvcWithDefaultRoute();
}

In my _Layout.cshtml I want to use a custom property from my MyPrincipal:

...
@if (User is MyPrincipal) {
  <do stuff>
}
...

So far so good, the user is recognized as MyPrincipal.

But when I add a global Authorization policy:

public void ConfigureServices(IServiceCollection services) {
  services.AddMvc(options => {
    var policy = new AuthorizationPolicyBuilder(CookieAuthenticationDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser()
        .Build();
    options.Filters.Add(new AuthorizeFilter(policy));
  });
}

Suddenly, the User in _Layout is just a ClaimsPrincipal.

How can I either stop MVC from replacing my principal, or hook into the pipeline after the authorization policy has completed?

P.S. I am using the ASP.NET Core 2.0 Preview 2, in case it matters.

Upvotes: 9

Views: 4393

Answers (1)

Dustin Kingen
Dustin Kingen

Reputation: 21275

The PolicyEvaluator is authenticating the AuthenticationScheme which replaces the Principal. To fix this remove the AuthenticationScheme parameter from the AuthorizationPolicyBuilder constructor.

var policy = new AuthorizationPolicyBuilder()
    .RequireAuthenticatedUser()
    .Build();

This will apply the policy to all authentication schemes and assumes you have called HttpContext.Authentication.SignInAsync elsewhere.

Upvotes: 4

Related Questions