Search code examples
.netazure-functions.net-6.0asp.net-core-middleware

.NET6 Azure Functions Custom Auth Middleware Returns 204 status code instead of 401


I created a middleware on a .NET6 Isolated azure functions project to authorize a http function request. I got the authorization part working well, just that it returns the wrong status code (204 instead of 401). Nothing looks out of place in the code to me. Could I be missing something or the IFunctionsWorkerMiddleware interface is buggy somehow?

public class TokenValidationMiddleware : IFunctionsWorkerMiddleware
{
    private readonly ILogger _logger;
    private readonly List<string> _userIds = new() { "user1" };

    public TokenValidationMiddleware(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<TokenValidationMiddleware>();
    }

    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        var request = await context.GetHttpRequestDataAsync();
        var response = request?.CreateResponse(HttpStatusCode.Unauthorized);
        response?.Headers.Add("Content-Type", "text/plain; charset=utf-8");

        if (request?.Headers.TryGetValues("Authorization", out var headers) == true)
        {
            foreach (var header in headers)
            {
                if (!header.StartsWith("Bearer ")) continue;
                var token = header["Bearer ".Length..]; //
                if (string.IsNullOrEmpty(token))
                {
                    _logger.LogWarning("Token is empty");
                    response?.WriteString("Authorization token is empty");
                    return;
                }
                var tokenHandler = new JwtSecurityTokenHandler();
                try
                {
                    var jwtToken = tokenHandler.ReadJwtToken(token);
                    var userId = jwtToken.Claims.First(x => x.Type == "sub").Value;
                    if (_userIds.Contains(userId))
                    {
                        await next(context);
                        break;
                    }
                    else
                    {
                        response?.WriteString("User is not authorized");
                        return;
                    }
                }
                catch (Exception e)
                {
                    _logger.LogWarning(e, "Token is invalid");
                    response?.WriteString("Token is invalid");
                    return;
                }
            }
        }
        else
        {
            response?.WriteString("Unauthorized request");
        }
    }
} 

Solution

  • I finally figured it out. All I had to do was to change the lines where I had response?.WriteString("some message"); to

    await response.WriteAsJsonAsync(new { ResponseText = "some message" }, response.StatusCode); // I either use the statusCode of the response created at the top or specify a different status code

    Finally, I set the invocation result with the response by calling the following after the line above;

    context.GetInvocationResult().Value = response;