Aspnetcore.docs: Authorization overload fix RequireAuthorization

Created on 21 Aug 2019  Â·  12Comments  Â·  Source: dotnet/AspNetCore.Docs

I'm using .Net Core 3.0 Preview 8

The #authorization section talks about how middleware can be authorized and

If the app uses an AuthorizeFilter as a global filter in MVC, we recommend refactoring the code to provide a policy to the UseAuthorization middleware.

In the following example, a custom policy to be applied to all requests when UseAuthorization is called, and the HomeController allows access without the user signing into the app:

Followed by suggestion the call to

// Configure method
app.UseAuthorization(new AuthorizationPolicyBuilder().Build()));
app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });

But app.UseAuthorization() does not have an overload taking a policy. So my next guess was this:

// ConfigureServices method
services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .RequireScope("ScopeName")
        .Build();
});
// omitted call to services.AddAuthentication().AddIdentityServerAuthentication() ...

Assuming if the default policy was to require authentication with my scope, that all endpoints would 401 out if no Bearer token was present. Also, my understanding was such that I remove the global AuthorizeFilter in MVC or SignalR, such as

// ConfigureServices method
services.AddControllersWithViews(options =>
{
    options.Filters.Add(new AuthorizeFilter());
...

But it does not appear to be the case, requests go through. Overall, I do not know how to use the new Authorization middleware, or how to setup globally required Authorization on any endpoint, which appears to be the suggestion in the current docs (Middleware, MVC, or SignalR), and the docs appear to be for an older preview (advising to use an overload of UseAuthorization() that does not exist) or just plain missing (IE, the aspnet/core/security/authorization/policies section of the docs does not appear updated for 3.0).


Document Details

⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

P1 Source - Docs.ms

Most helpful comment

I would suggest both, since they are slightly different, the RequireAuthorization only applies to the default controller route, while demonstrating the fallback scenario to show how to protect all endpoints.

Does that make sense?

All 12 comments

So you're wanting to apply an auth policy to a single endpoint?

Something like the below?

app.UseEndpoints(endpoints =>
{
    endpoints.MapDefaultControllerRoute()
        .RequireAuthorization(new AuthorizeAttribute("policyName"));
});

Thanks for the fast response!

I was hoping to secure _all_ endpoints, MVC/SignalR by default, and I have some middleware that runs before MVC/SignalR that I would like to know is authenticated or not. I didn't realize there was a RequiresAuthoriztion() chain call. But now I see that in the HealthChecks example.

So I took your example:

services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .RequireScope("ScopeName")
        .Build();
});

...

app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<SessionsHub>("/Sessions").RequireAuthorization();
    endpoints.MapControllers().RequireAuthorization();
});

And that works, nice! So this is the new advice for adding authorization to MVC/SignalR then? If I'm in middleware, do I just look at HttpClient like this? if (httpContext.User?.Identity?.IsAuthenticated is true) or call httpClient.AuthenticateAsync call? Or is there a new way to look at auth in middleware with the 3.0 auth middleware in place?
IE:

app.UseAuthentication();
app.UseAuthorization();
app.UseMiddleware<SomethingCustom>(); // Wants to know if user is authorized or not.
app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<SessionsHub>("/Sessions").RequireAuthorization();
    endpoints.MapControllers().RequireAuthorization();
});

@rynowak or @HaoK what is the recommended way to enforce authentication for all endpoints and middleware?

UseAuthorization middleware with the fallback policy should do that

something like https://github.com/aspnet/AspNetCore/blob/8c02467b4a218df3b1b0a69bceb50f5b64f482b1/src/Security/Authentication/Negotiate/samples/NegotiateAuthSample/Startup.cs#L20 would require an authenticated user by default. You can set the policy to something different, Fallback is used when no policy is specified, its slightly different than default policy which is used when [Authorize] is specified

Alright, so just to make sure I'm fully understanding, if we take my code again, and use FallbackPolicy, and remove .RequireAuthorization() from the MVC/SignalR calls, then that's the right approach in 3.0 for globally requiring authentication? Do I need to worry about setting the DefaultPolicy if I take this approach?

services.AddAuthorization(options =>
{
    options.FallbackPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .RequireScope("ScopeName")
        .Build();
});

...

app.UseAuthentication();
app.UseAuthorization();
app.UseMiddleware<SomethingCustom>(); // Wants to know if user is authorized or not.
app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<SessionsHub>("/Sessions");
    endpoints.MapControllers();
});

And in middleware, just look at httpContext.User.Identity?

You guys have been very helpful and quick to respond, thank you!

@HaoK should we update the doc or is this issue enough to doc this? This issues is discoverable from the end of the doc page:
image

We should update the doc, I can take a look at this next week

@AdamDotNet correct, FallbackPolicy lets you avoid specifying the default policy or worrying about adding the Authorize attribute/metadata anywhere, as the middleware will take care of applying it consistently (that's the idea behind the feature anyways, if its not, that would be a bug)

@AdamDotNet can you write up an update for the doc (in this issue), or PR the doc. You can edit the doc in the browser and make a PR.

@Rick-Anderson - Sure. Do you suggest changing the existing example to remove the incorrect call to app.UseAuthorization(new AuthorizationPolicyBuilder().Build())); + add modify endpoints.MapDefaultControllerRoute(); to endpoints.MapDefaultControllerRoute().RequireAuthorization();? Or to mention the FallbackPolicy? Both?

@haok can you help @AdamDotNet get the update started?

I would suggest both, since they are slightly different, the RequireAuthorization only applies to the default controller route, while demonstrating the fallback scenario to show how to protect all endpoints.

Does that make sense?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

danroth27 picture danroth27  Â·  3Comments

davisnw picture davisnw  Â·  3Comments

YeyoCoder picture YeyoCoder  Â·  3Comments

wgutierrezr picture wgutierrezr  Â·  3Comments

fabich picture fabich  Â·  3Comments