-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit b5c1a12
Showing
79 changed files
with
5,288 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
45 changes: 45 additions & 0 deletions
45
BlazingAuth.Permissions.Client/AttributeAuthorizationHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using Microsoft.AspNetCore.Authorization; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Components; | ||
using System.Reflection; | ||
using System.Linq; | ||
|
||
namespace BlazingAuth.Permissions.Client | ||
{ | ||
public abstract class AttributeAuthorizationHandler<TRequirement, TAttribute> : AuthorizationHandler<TRequirement> | ||
where TRequirement : IAuthorizationRequirement | ||
where TAttribute : Attribute | ||
{ | ||
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement) | ||
{ | ||
var attributes = new List<TAttribute>(); | ||
|
||
if (context.Resource is null) | ||
throw new ArgumentNullException(nameof(context.Resource), "Resource is not specified. Did you forget to set Resource=\"@routeData\" ?"); | ||
|
||
if (context.Resource is AuthorizePermissionView permissionsView) | ||
{ | ||
// Custom AuthorizePermissionView component | ||
return HandleRequirementAsync(context, requirement, permissionsView); | ||
} | ||
else if (context.Resource is RouteData routeData && routeData?.PageType is not null) | ||
{ | ||
// Add all AuthorizePermssion attributes to the list | ||
attributes.AddRange(GetAttributes(routeData.PageType)); | ||
} | ||
|
||
// Handle all AuthorizePermssion attributes (if any) | ||
return HandleRequirementAsync(context, requirement, attributes); | ||
} | ||
|
||
protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement, IEnumerable<TAttribute> attributes); | ||
protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement, AuthorizePermissionView permissionsView); | ||
|
||
private static IEnumerable<TAttribute> GetAttributes(MemberInfo memberInfo) | ||
{ | ||
return memberInfo.GetCustomAttributes(typeof(TAttribute), false).Cast<TAttribute>(); | ||
} | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
BlazingAuth.Permissions.Client/AuthorizePermissionAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using Microsoft.AspNetCore.Authorization; | ||
using System; | ||
|
||
namespace BlazingAuth.Permissions.Client | ||
{ | ||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] | ||
public class AuthorizePermissionAttribute : AuthorizeAttribute | ||
{ | ||
public string[] OrPermissons { get; } | ||
|
||
public AuthorizePermissionAttribute(params string[] orPermissons) : base(BlazingAuthPolicies.Permission) | ||
{ | ||
OrPermissons = orPermissons; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
using System; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Components; | ||
using Microsoft.AspNetCore.Components.Authorization; | ||
|
||
namespace BlazingAuth.Permissions.Client | ||
{ | ||
/// <summary> | ||
/// Displays differing content depending on the user's authorization status. | ||
/// </summary> | ||
public class AuthorizePermissionView : AuthorizeViewCore | ||
{ | ||
private readonly IAuthorizeData[] selfAsAuthorizeData; | ||
|
||
/// <summary> | ||
/// Constructs an instance of <see cref="AuthorizeView"/>. | ||
/// </summary> | ||
public AuthorizePermissionView() | ||
{ | ||
selfAsAuthorizeData = new[] { new AuthorizeDataAdapter(this) }; | ||
Resource = this; | ||
} | ||
|
||
/// <summary> | ||
/// A comma delimited list of roles that are allowed to display the content. | ||
/// </summary> | ||
[Parameter] public string? Roles { get; set; } | ||
|
||
/// <summary> | ||
/// A comma delimited list of permissions that are needed to display the content. | ||
/// </summary> | ||
[Parameter] public string? AndPermissions { get; set; } | ||
|
||
/// <summary> | ||
/// A list of permissions that only one of is needed to display the content. | ||
/// Gets overriden by <see cref="AndPermissions"/> if specified. | ||
/// </summary> | ||
[Parameter] public string[]? AndPermissionsList { get; set; } | ||
|
||
/// <summary> | ||
/// A comma delimited list of permissions that only one of is needed to display the content. | ||
/// </summary> | ||
[Parameter] public string? OrPermissions { get; set; } | ||
|
||
/// <summary> | ||
/// A list of permissions that only one of is needed to display the content. | ||
/// Gets overriden by <see cref="OrPermissions"/> if specified. | ||
/// </summary> | ||
[Parameter] public string[]? OrPermissionsList { get; set; } | ||
|
||
/// <summary> | ||
/// Gets the data used for authorization. | ||
/// </summary> | ||
protected override IAuthorizeData[] GetAuthorizeData() | ||
=> selfAsAuthorizeData; | ||
|
||
protected override Task OnParametersSetAsync() | ||
{ | ||
// Set lists | ||
AndPermissionsList ??= AndPermissions?.Split(','); | ||
OrPermissionsList ??= OrPermissions?.Split(','); | ||
|
||
// Proceed with authorization | ||
return base.OnParametersSetAsync(); | ||
} | ||
} | ||
|
||
// This is so the AuthorizeView can avoid implementing IAuthorizeData (even privately) | ||
internal class AuthorizeDataAdapter : IAuthorizeData | ||
{ | ||
private readonly AuthorizePermissionView component; | ||
|
||
public AuthorizeDataAdapter(AuthorizePermissionView component) | ||
{ | ||
this.component = component ?? throw new ArgumentNullException(nameof(component)); | ||
} | ||
|
||
public string? Policy | ||
{ | ||
get => BlazingAuthPolicies.Permission; | ||
set => throw new NotSupportedException(); | ||
} | ||
|
||
public string? Roles | ||
{ | ||
get => component.Roles; | ||
set => throw new NotSupportedException(); | ||
} | ||
|
||
// AuthorizeView doesn't expose any such parameter, as it wouldn't be used anyway, | ||
// since we already have the ClaimsPrincipal by the time AuthorizeView gets involved. | ||
public string? AuthenticationSchemes | ||
{ | ||
get => null; | ||
set => throw new NotSupportedException(); | ||
} | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
BlazingAuth.Permissions.Client/BlazingAuth.Permissions.Client.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Razor"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<LangVersion>10</LangVersion> | ||
<nullable>enable</nullable> | ||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> | ||
<Company /> | ||
<Authors>Dusty</Authors> | ||
<Description>Easy to use, claims and policy based permission authorization for Blazor (client project)</Description> | ||
<RepositoryType>git</RepositoryType> | ||
<PackageTags>blazor auth authorization authentication permission permissions blazing claims claim policy auth secure safe</PackageTags> | ||
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance> | ||
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile> | ||
<PackageReadmeFile>README.md</PackageReadmeFile> | ||
<SignAssembly>False</SignAssembly> | ||
<GenerateDocumentationFile>False</GenerateDocumentationFile> | ||
<RepositoryUrl>https://github.com/TheDusty01/BlazingAuth.Permissions</RepositoryUrl> | ||
<Version>6.0.0</Version> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<None Include="..\README.md"> | ||
<Pack>True</Pack> | ||
<PackagePath>\</PackagePath> | ||
</None> | ||
|
||
<None Include="..\LICENSE.txt"> | ||
<Pack>True</Pack> | ||
<PackagePath>\</PackagePath> | ||
</None> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.4" /> | ||
<PackageReference Include="Microsoft.AspNetCore.Components" Version="6.0.4" /> | ||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="6.0.4" /> | ||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="6.0.4" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\BlazingAuth.Permissions\BlazingAuth.Permissions.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
62 changes: 62 additions & 0 deletions
62
BlazingAuth.Permissions.Client/BlazingAuthAccountClaimsPrincipalFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
using Microsoft.AspNetCore.Components.WebAssembly.Authentication; | ||
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Security.Claims; | ||
using System.Text; | ||
using System.Text.Json; | ||
using System.Threading.Tasks; | ||
|
||
namespace BlazingAuth.Permissions.Client | ||
{ | ||
public class BlazingAuthAccountClaimsPrincipalFactory : AccountClaimsPrincipalFactory<RemoteUserAccount> | ||
{ | ||
public BlazingAuthAccountClaimsPrincipalFactory(IAccessTokenProviderAccessor accessor) : base(accessor) | ||
{ | ||
} | ||
|
||
public override async ValueTask<ClaimsPrincipal> CreateUserAsync(RemoteUserAccount account, RemoteAuthenticationUserOptions options) | ||
{ | ||
var user = await base.CreateUserAsync(account, options); | ||
if (user.Identity?.IsAuthenticated == true) | ||
{ | ||
var identity = (ClaimsIdentity)user.Identity; | ||
|
||
ClaimArrayToMultipleClaims(account, identity, identity.RoleClaimType); | ||
ClaimArrayToMultipleClaims(account, identity, BlazingAuthClaims.Permission.Type); | ||
} | ||
|
||
return user; | ||
} | ||
|
||
protected static void ClaimArrayToMultipleClaims(RemoteUserAccount account, ClaimsIdentity identity, string claimType) | ||
{ | ||
var claims = identity.FindAll(claimType).ToArray(); | ||
if (!claims.Any()) | ||
return; | ||
|
||
foreach (var existingClaim in claims) | ||
{ | ||
identity.RemoveClaim(existingClaim); | ||
} | ||
|
||
var itemElem = account.AdditionalProperties[claimType]; | ||
if (itemElem is JsonElement items) | ||
{ | ||
if (items.ValueKind == JsonValueKind.Array) | ||
{ | ||
foreach (var item in items.EnumerateArray()) | ||
{ | ||
identity.AddClaim(new Claim(claimType, item.GetString()!)); | ||
} | ||
} | ||
else | ||
{ | ||
identity.AddClaim(new Claim(claimType, items.GetString()!)); | ||
} | ||
} | ||
|
||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.DependencyInjection.Extensions; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace BlazingAuth.Permissions.Client | ||
{ | ||
public static class BlazingAuthExtensions | ||
{ | ||
public static IServiceCollection AddBlazingAuthPermissions(this IServiceCollection services) | ||
{ | ||
services.AddAuthorizationCore(options => | ||
{ | ||
options.AddPolicy(BlazingAuthPolicies.Permission, BlazingAuthPolicies.PermissionPolicy); | ||
}); | ||
|
||
services.AddSingleton<IAuthorizationHandler, PermissionAuthorizationHandler>(); | ||
|
||
return services; | ||
} | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
BlazingAuth.Permissions.Client/PermissionAuthorizationHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using BlazingAuth.Permissions.Requirements; | ||
using Microsoft.AspNetCore.Authorization; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Text.Json; | ||
using System.Threading.Tasks; | ||
|
||
namespace BlazingAuth.Permissions.Client | ||
{ | ||
public class PermissionAuthorizationHandler : AttributeAuthorizationHandler<PermissionAuthorizationRequirement, AuthorizePermissionAttribute> | ||
{ | ||
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionAuthorizationRequirement requirement, IEnumerable<AuthorizePermissionAttribute> attributes) | ||
{ | ||
foreach (var permissionAttribute in attributes) | ||
{ | ||
if (!context.User.HasAnyPermission(permissionAttribute.OrPermissons)) | ||
{ | ||
context.Fail(new AuthorizationFailureReason(this, "User doesn't have the required permissions.")); | ||
return Task.CompletedTask; | ||
} | ||
} | ||
|
||
context.Succeed(requirement); | ||
return Task.CompletedTask; | ||
} | ||
|
||
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionAuthorizationRequirement requirement, AuthorizePermissionView permissionsView) | ||
{ | ||
bool andPermissionsValid = permissionsView.AndPermissionsList is null || context.User.HasPermissions(permissionsView.AndPermissionsList); | ||
bool orPermissionsValid = permissionsView.OrPermissionsList is null || context.User.HasAnyPermission(permissionsView.OrPermissionsList); | ||
|
||
if (!andPermissionsValid || !orPermissionsValid) | ||
{ | ||
context.Fail(new AuthorizationFailureReason(this, "User doesn't have the required permissions.")); | ||
return Task.CompletedTask; | ||
} | ||
|
||
context.Succeed(requirement); | ||
return Task.CompletedTask; | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
BlazingAuth.Permissions.Server/AuthorizePermissionAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using Microsoft.AspNetCore.Mvc; | ||
|
||
namespace BlazingAuth.Permissions.Server | ||
{ | ||
public class AuthorizePermissionAttribute : TypeFilterAttribute | ||
{ | ||
public AuthorizePermissionAttribute(params string[] orPermissons) : base(typeof(PermissionAuthorizationFilter)) | ||
{ | ||
Arguments = new object[] { orPermissons }; | ||
} | ||
} | ||
} |
Oops, something went wrong.