I’m currently working on a .NET Core project that utilizes both regular API endpoints and GraphQL endpoints using HotChocolate. I implemented the authentication for both endpoints and it working.
[Authorize] // this attribute from using Microsoft.AspNetCore.Authorization;
[HttpPost("GetCountryHolidays")]
public async Task<IList<GetCountryDetails>> GetHolidays(GetHolidaysCommand command)
{
return await _mediator.Send(command);
}
Graphql endpoint
[Authorize] // this attribute from HotChocolate.AspNetCore.Authorization;
public async Task<bool> CreateUser(User Command)
{
await _mediator.Send(query);
return true;
}
above implementation is working.
Then I need to implement the authorization. I need to check the "permission" claim in the access token. so I have implemented a custom authorization attribute called "HasPermission" to check for permissions based on claims in the access token. This attribute works perfectly for regular API endpoints with the [Authorize] attribute, but it doesn’t seem to work for GraphQL endpoints.
this is my "HasPermission" implementation
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
namespace MySampleProject.Tenant.Api
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class HasPermissionAttribute : Attribute, IAuthorizationFilter
{
private string[] permissions { get; set; }
private bool allowEServiceUser { get; set; }
public HasPermissionAttribute(params string[] permissions)
{
if (permissions != null && permissions.Length > 0 && permissions.Any(x => string.IsNullOrWhiteSpace(x)))
throw new ArgumentNullException("permissions", "Permissions value is not submitted or invalid!");
this.permissions = permissions;
this.allowEServiceUser = false;
}
public HasPermissionAttribute(bool allowEServiceUser = false, params string[] permissions)
{
if (permissions != null && permissions.Length > 0 && permissions.Any(x => string.IsNullOrWhiteSpace(x)))
throw new ArgumentNullException("permissions", "Permissions value is not submitted or invalid!");
this.permissions = permissions;
this.allowEServiceUser = allowEServiceUser;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
if ((permissions != null && permissions.Length > 0) && !(permissions.Any(x => string.IsNullOrEmpty(x))))
{
if (!context.HttpContext.HasPermisions(permissions, allowEServiceUser))
{
context.Result = new UnauthorizedResult();
}
}
}
}
public static class HttpContextExtension
{
public static bool HasPermisions(this HttpContext context, string[] permissionKeys, bool allowEserviceUser = false)
{
if (context == null)
return false;
List<string> permissions = context.User.Claims.Where(x => x.Type == "permissions").Select(x => x.Value).ToList();
return permissions.Intersect(permissionKeys).Any();
}
}
}
this is how I call it with regular API endpoints
[HttpPost("admin")]
[HasPermission("CAN_ADMIN_ONLY")]
public bool TestAdmin()
{
return true;
}
it works with regular API endpoints. However, when I use the same HasPermission attribute on a GraphQL endpoint, it doesn’t seem to have any effect, and the endpoint remains accessible without any permission checks:
Is there something specific I need to do to make it work for GraphQL endpoints with HotChocolate? Any insights or guidance would be greatly appreciated.