Implementing Authorization in .NET Core APIs

By FoxLearn 1/10/2025 3:30:02 AM   56
When building APIs in .NET Core, not all endpoints need the same level of security or authorization.

To enforce this, you can apply a custom attribute to your API methods, ensuring that only requests with a valid authorization token can access them.

First, you need to create a custom attribute, AuthTokenRequired, that can be applied to the endpoints in your controller. This attribute will ensure that the endpoint is protected by token-based authentication.

Creating the Custom Authorization Attribute

We start by defining the custom AuthTokenRequiredAttribute. This will utilize TypeFilterAttribute to link to an authorization filter class (TokenAuthorizationFilter).

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using System.Security.Authentication;

namespace MyApp
{
    // Custom authorization filter that validates the token
    [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
    public class TokenAuthorizationFilter : Attribute, IAuthorizationFilter
    {
        private readonly IRepository _repository;
        private readonly IWebHostEnvironment _environment;

        public TokenAuthorizationFilter(IRepository repository, IWebHostEnvironment environment)
        {
            _repository = repository;
            _environment = environment;
        }

        public void OnAuthorization(AuthorizationFilterContext context)
        {
            // Skip token validation in the development environment
            if (_environment.IsDevelopment())
                return;

            // Retrieve the token from the request header
            var token = context.HttpContext.Request.Headers["AuthorizationToken"];
            if (string.IsNullOrEmpty(token))
                throw new AuthenticationException("Unauthorized");

            // Validate the token (this is just an example check)
            if (token != "valid-token")
                throw new AuthenticationException("Unauthorized");
        }
    }
}

In this example:

  1. AuthTokenRequiredAttribute: This attribute is applied to controller methods and specifies that the method requires a valid token for access. It triggers the TokenAuthorizationFilter.
  2. TokenAuthorizationFilter: This is the actual logic that runs when the attribute is used. It checks the request headers for a valid authorization token and throws an AuthenticationException if the token is missing or invalid.

Applying the Attribute to Controller Actions

Once the custom attribute is in place, you can now decorate your API actions with it. In this case, the GetProfile method requires a valid authorization token before it can be executed.

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class ProfileController : Controller
    {
        [HttpGet()]
        [AuthTokenRequired]  // This endpoint requires a valid authorization token
        public async Task<IActionResult> GetProfile()
        {
            try
            {
                // If the token is invalid, an exception will be thrown before this code is reached.
                var profile = await _repository.GetProfileAsync();
                return Ok(profile);
            }
            catch (Exception ex)
            {
                return Unauthorized(new { message = ex.Message });
            }
        }
    }
}

In this example:

  1. Applying the Attribute: The [AuthTokenRequired] attribute is placed above the GetProfile action in the controller. This indicates that this endpoint requires an authorization token in the request header.

  2. Authorization Flow: When a request hits this endpoint, the TokenAuthorizationFilter checks the request header for the token. If the token is missing or invalid, the request is denied by throwing an AuthenticationException.

  3. Handling Unauthorized Requests: If the authorization fails, the action method is never reached.