add support for dynamic authorization policies

This commit is contained in:
Shaun Walker 2022-11-04 08:08:10 -04:00
parent 23d1dd23d1
commit 2aa6eb90e2
4 changed files with 57 additions and 30 deletions

View File

@ -6,11 +6,11 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Reflection.Metadata;
using System.Runtime.Loader;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
@ -47,22 +47,6 @@ namespace Microsoft.Extensions.DependencyInjection
return services;
}
public static IServiceCollection AddOqtaneAuthorizationPolicies(this IServiceCollection services)
{
services.AddAuthorizationCore(options =>
{
options.AddPolicy(PolicyNames.ViewPage, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.View)));
options.AddPolicy(PolicyNames.EditPage, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.Edit)));
options.AddPolicy(PolicyNames.ViewModule, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Module, PermissionNames.View)));
options.AddPolicy(PolicyNames.EditModule, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Module, PermissionNames.Edit)));
options.AddPolicy(PolicyNames.ViewFolder, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.View)));
options.AddPolicy(PolicyNames.EditFolder, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.Edit)));
options.AddPolicy(PolicyNames.ListFolder, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.Browse)));
});
return services;
}
public static OqtaneSiteOptionsBuilder AddOqtaneSiteOptions(this IServiceCollection services)
{
return new OqtaneSiteOptionsBuilder(services);
@ -76,6 +60,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddSingleton<IConfigManager, ConfigManager>();
services.AddSingleton<ILoggerProvider, FileLoggerProvider>();
services.AddSingleton<AutoValidateAntiforgeryTokenFilter>();
services.AddSingleton<IAuthorizationPolicyProvider, AuthorizationPolicyProvider>();
return services;
}

View File

@ -0,0 +1,54 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Oqtane.Shared;
using System.Threading.Tasks;
namespace Oqtane.Security
{
public class AuthorizationPolicyProvider : DefaultAuthorizationPolicyProvider
{
private readonly AuthorizationOptions _options;
private readonly IConfiguration _configuration;
public AuthorizationPolicyProvider(IOptions<AuthorizationOptions> options, IConfiguration configuration) : base(options)
{
_options = options.Value;
_configuration = configuration;
}
public override async Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
{
// check static policies first
policyName = GetPolicyName(policyName);
var policy = await base.GetPolicyAsync(policyName);
if (policy == null)
{
// policy names must be in the form of "Entity:Permission" ie. "User:Read"
if (policyName.Contains(":"))
{
var entityName = policyName.Split(':')[0];
var permissionName = policyName.Split(':')[1];
policy = new AuthorizationPolicyBuilder()
.AddRequirements(new PermissionRequirement(entityName, permissionName))
.Build();
// add policy to the AuthorizationOptions
_options.AddPolicy(policyName, policy);
}
}
return policy;
}
private string GetPolicyName(string policyName)
{
// backward compatibility for legacy static policy names
if (policyName == PolicyNames.ViewModule) policyName = "Module:View";
if (policyName == PolicyNames.EditModule) policyName = "Module:Edit";
return policyName;
}
}
}

View File

@ -127,8 +127,6 @@ namespace Oqtane
.WithSiteIdentity()
.WithSiteAuthentication();
services.AddOqtaneAuthorizationPolicies();
services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());

View File

@ -1,19 +1,9 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Oqtane.Shared
{
// static PolicyNames are deprecated and replaced with dynamic policies
public class PolicyNames
{
public const string ViewPage = "ViewPage";
public const string EditPage = "EditPage";
public const string ViewModule = "ViewModule";
public const string EditModule = "EditModule";
public const string ViewFolder = "ViewFolder";
public const string EditFolder = "EditFolder";
public const string ListFolder = "ListFolder";
}
}