GQL Authorization Middleware implemented, will take care of controllers next.
This commit is contained in:
parent
45279da02b
commit
3e6c76ab18
31
Demo/Security/CommandAndQueryAuthorizationService.cs
Normal file
31
Demo/Security/CommandAndQueryAuthorizationService.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using PoweredSoft.CQRS.Abstractions.Security;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Demo.Security
|
||||
{
|
||||
public class CommandAndQueryAuthorizationService : IQueryAuthorizationService, ICommandAuthorizationService
|
||||
{
|
||||
private readonly IHttpContextAccessor httpContextAccessor;
|
||||
|
||||
public CommandAndQueryAuthorizationService(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
this.httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
public Task<AuthorizationResult> IsAllowedAsync(Type queryOrCommandType, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var authResult = httpContextAccessor.HttpContext.Request.Query["auth-result"].FirstOrDefault();
|
||||
if (authResult == "Unauthorized")
|
||||
return Task.FromResult(AuthorizationResult.Unauthorized);
|
||||
else if (authResult == "Forbidden")
|
||||
return Task.FromResult(AuthorizationResult.Forbidden);
|
||||
|
||||
return Task.FromResult(AuthorizationResult.Allowed);
|
||||
}
|
||||
}
|
||||
}
|
@ -22,6 +22,8 @@ using PoweredSoft.Data.Core;
|
||||
using PoweredSoft.DynamicQuery;
|
||||
using System.Linq;
|
||||
using PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery;
|
||||
using PoweredSoft.CQRS.Abstractions.Security;
|
||||
using Demo.Security;
|
||||
|
||||
namespace Demo
|
||||
{
|
||||
@ -41,6 +43,9 @@ namespace Demo
|
||||
AddDynamicQueries(services);
|
||||
AddCommands(services);
|
||||
|
||||
services.AddHttpContextAccessor();
|
||||
services.AddTransient<IQueryAuthorizationService, CommandAndQueryAuthorizationService>();
|
||||
services.AddTransient<ICommandAuthorizationService, CommandAndQueryAuthorizationService>();
|
||||
services.AddTransient<IAsyncQueryableHandlerService, InMemoryQueryableHandler>();
|
||||
services.AddPoweredSoftDataServices();
|
||||
services.AddPoweredSoftDynamicQuery();
|
||||
|
@ -0,0 +1,9 @@
|
||||
namespace PoweredSoft.CQRS.Abstractions.Security
|
||||
{
|
||||
public enum AuthorizationResult
|
||||
{
|
||||
Unauthorized,
|
||||
Forbidden,
|
||||
Allowed
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PoweredSoft.CQRS.Abstractions.Security
|
||||
{
|
||||
public interface ICommandAuthorizationService
|
||||
{
|
||||
Task<AuthorizationResult> IsAllowedAsync(Type commandType, CancellationToken cancellationToken = default);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PoweredSoft.CQRS.Abstractions.Security
|
||||
{
|
||||
|
||||
public interface IQueryAuthorizationService
|
||||
{
|
||||
Task<AuthorizationResult> IsAllowedAsync(Type queryType, CancellationToken cancellationToken = default);
|
||||
}
|
||||
}
|
@ -61,6 +61,9 @@ namespace PoweredSoft.CQRS.GraphQL.HotChocolate.DynamicQuery
|
||||
|
||||
f.Type(resultType);
|
||||
|
||||
// security middleware
|
||||
f.Use((sp, d) => new QueryAuthorizationMiddleware(q.QueryType, d));
|
||||
|
||||
// middleware to validate.
|
||||
f.Use<QueryValidationMiddleware>();
|
||||
|
||||
|
@ -0,0 +1,46 @@
|
||||
using HotChocolate;
|
||||
using HotChocolate.Resolvers;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using PoweredSoft.CQRS.Abstractions.Security;
|
||||
|
||||
namespace PoweredSoft.CQRS.GraphQL.HotChocolate
|
||||
{
|
||||
internal class MutationAuthorizationMiddleware
|
||||
{
|
||||
private readonly Type mutationType;
|
||||
private readonly FieldDelegate _next;
|
||||
|
||||
public MutationAuthorizationMiddleware(Type mutationType,FieldDelegate next)
|
||||
{
|
||||
this.mutationType = mutationType;
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(IMiddlewareContext context)
|
||||
{
|
||||
var mutationAuthorizationService = context.Service<IServiceProvider>().GetService<ICommandAuthorizationService>();
|
||||
if (mutationAuthorizationService != null)
|
||||
{
|
||||
var authorizationResult = await mutationAuthorizationService.IsAllowedAsync(mutationType);
|
||||
if (authorizationResult != AuthorizationResult.Allowed)
|
||||
{
|
||||
var eb = ErrorBuilder.New()
|
||||
.SetMessage(authorizationResult == AuthorizationResult.Unauthorized ? "Unauthorized" : "Forbidden")
|
||||
.SetCode("AuthorizationResult")
|
||||
.SetExtension("StatusCode", authorizationResult == AuthorizationResult.Unauthorized ? "401" : "403")
|
||||
.SetPath(context.Path)
|
||||
.AddLocation(context.Selection.SyntaxNode);
|
||||
|
||||
context.Result = eb.Build();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
using HotChocolate;
|
||||
using HotChocolate.Resolvers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using PoweredSoft.CQRS.Abstractions.Security;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PoweredSoft.CQRS.GraphQL.HotChocolate
|
||||
{
|
||||
public class QueryAuthorizationMiddleware
|
||||
{
|
||||
private readonly Type queryType;
|
||||
private readonly FieldDelegate _next;
|
||||
|
||||
public QueryAuthorizationMiddleware(Type queryType, FieldDelegate next)
|
||||
{
|
||||
this.queryType = queryType;
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(IMiddlewareContext context)
|
||||
{
|
||||
var queryAuthorizationService = context.Service<IServiceProvider>().GetService<IQueryAuthorizationService>();
|
||||
if (queryAuthorizationService != null)
|
||||
{
|
||||
var authorizationResult = await queryAuthorizationService.IsAllowedAsync(queryType);
|
||||
if (authorizationResult != AuthorizationResult.Allowed)
|
||||
{
|
||||
var eb = ErrorBuilder.New()
|
||||
.SetMessage(authorizationResult == AuthorizationResult.Unauthorized ? "Unauthorized" : "Forbidden")
|
||||
.SetCode("AuthorizationResult")
|
||||
.SetExtension("StatusCode", authorizationResult == AuthorizationResult.Unauthorized ? "401" : "403")
|
||||
.SetPath(context.Path)
|
||||
.AddLocation(context.Selection.SyntaxNode);
|
||||
|
||||
context.Result = eb.Build();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,8 @@ using HotChocolate.Types;
|
||||
using PoweredSoft.CQRS.Abstractions;
|
||||
using PoweredSoft.CQRS.Abstractions.Discovery;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace PoweredSoft.CQRS.GraphQL.HotChocolate
|
||||
@ -28,11 +30,25 @@ namespace PoweredSoft.CQRS.GraphQL.HotChocolate
|
||||
var queryField = desc.Field(q.LowerCamelCaseName);
|
||||
var typeToGet = typeof(IQueryHandler<,>).MakeGenericType(q.QueryType, q.QueryResultType);
|
||||
|
||||
queryField.Type(q.QueryResultType);
|
||||
queryField.Use((sp, d) => new QueryAuthorizationMiddleware(q.QueryType, d));
|
||||
|
||||
// TODO.
|
||||
// always required.
|
||||
//queryField.Use((sp, d) => new QueryAuthorizationMiddleware(q.QueryType, d));
|
||||
// if its a IQueryable.
|
||||
if (q.QueryResultType.Namespace == "System.Linq" && q.QueryResultType.Name.Contains("IQueryable"))
|
||||
{
|
||||
//waiting on answer to be determined.
|
||||
/*var genericArgument = q.QueryResultType.GetGenericArguments().First();
|
||||
var type = new ListType(new NonNullType(new NamedTypeNode));
|
||||
queryField.Type(type);
|
||||
queryField.UsePaging();
|
||||
*/
|
||||
|
||||
queryField.Type(q.QueryResultType);
|
||||
}
|
||||
else
|
||||
{
|
||||
queryField.Type(q.QueryResultType);
|
||||
|
||||
}
|
||||
|
||||
if (q.QueryType.GetProperties().Length == 0)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user