dotnet / dotnet/aspnetcore

Introduce support for defining Authorization policies via Configuration

Open
#42,172 23 comments 0 reactions 0 assignees View on GitHub
area-auth area-minimal feature-minimal-hosting
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 6h
Merged PRs (30d)
290

Description

Spin-off of #39855 focusing on addition of top-level authorization configuration API.

Example matching `Authorization` changes to consider, allowing sharing of policies, etc.:

```csharp
var builder = WebApplication.CreateBuilder(args);

builder.Authentication.AddJwtBearer();
builder.Authorization.AddPolicy("HasProtectedAccess", policy =>
policy.RequireClaim("scope", "myapi:protected-access"));

var app = builder.Build();

app.MapGet("/hello", () => "Hello!");

app.MapGet("/hello-protected", () => "Hello, you are authorized to see this!")
.RequireAuthorization("HasProtectedAccess");

app.MapGet("/hello-also-protected", () => "Hello, you authorized to see this to!")
.RequireAuthorization("HasProtectedAccess");

app.Run();
```

The `WebApplicationBuilder.Authorization` property is typed as `AuthorizationOptions` allowing simple creation of policies and configuration of the default and fallback policies:

```csharp
builder.Authorization.AddPolicy("HasProtectedAccess", policy => policy.RequireClaim("scope", "myapi:protected-access"));
builder.Authorization.DefaultPolicy = builder.Authorization.GetPolicy("HasProtectedAccess");

// Consider new methods to enable easily setting default/fallback policies by name
builder.Authorization.SetDefaultPolicy("HasProtectedAccess");
builder.Authorization.SetFallbackPolicy("HasProtectedAccess");
```

The `WebApplicationBuilder` would register an `IConfigureOptions` in the services collection with a delegate that applies the settings.

Note this suggestion has a fundamental issue in that the `AuthorizationOptions` isn't designed to be mutated in this way, rather it should be configured via a callback registered in DI so that it runs at the appropriate time during app startup and composes with other code that wishes to configure it.

Perhaps instead the `Authentication` property should also read from configuration for authorization settings, and the `Authorization` property would be a new type that simply provides easy access to adding a configuration delegate, e.g.:

```jsonc
{
"Authorization": {
"DefaultPolicy": "HasProtectedAccess",
"FallbackPolicy": "",
"InvokeHandlersAfterFailure": true,
"Policies": {
"HasProtectedAccess": {
"Claims": [
{ "scope" : "myapi:protected-access" }
]
}
}
}
}
```

```csharp
builder.Authentication.AddJwtBearer();
builder.Authorization.Configure(authz =>
{
// Following is the code-based equivalent of config above
authz.AddPolicy("HasProtectedAccess", policy => policy.RequireClaim("scope", "myapi:protected-access"));
authz.DefaultPolicy = authz.GetPolicy("HasProtectedAccess");
});
```

Some other potential example policies as defined via configuration:

```jsonc
{
"Authorization": {
"DefaultPolicy": "HasProtectedAccess",
"Policies": {
"AuthenticatedUsers": {
"AuthenticationRequired": true
},
"Employees": {
"AuthenticationRequired": true,
"Roles": [ "Employees" ]
},
"OnlyHomers": {
"AuthenticationRequired": true,
"UserName": "Homer"
},
"ApiClients": {
"AuthenticationRequired": true,
// Any unrecognized properties are auto-mapped as claims perhaps?
"scope": [ "myapi:read", "myapi:protected-access" ]
}
}
}
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.