.NET6 Azure Functions自定义身份验证中间件返回204状态码而不是401。

huangapple go评论67阅读模式
英文:

.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 an 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");
        }
    }
}
英文:

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&lt;string&gt; _userIds = new() { &quot;user1&quot; };

    public TokenValidationMiddleware(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger&lt;TokenValidationMiddleware&gt;();
    }

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

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

答案1

得分: 1

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;

英文:

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

await response.WriteAsJsonAsync(new { ResponseText = &quot;some message&quot; }, 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;

答案2

得分: 0

以下是翻译好的部分:

你的中间件存在代码问题。

await _next(context); 应该放在 try...catch... 外部,并且无论如何都应该执行。

我的测试代码:

public async Task InvokeAsync(HttpContext context)
{
    try
    {
        string id = context.Request.Query["id"].ToString();
        if (id == "1")
        {
            context.Response.StatusCode = 201;
        }
        else if (id == "2")
        {
            context.Response.StatusCode = 401;
        }
    }
    catch (Exception)
    {
        context.Response.StatusCode = 401;
        throw;
    }
    // 做一些其他操作...
    await _next(context);
}

测试结果

.NET6 Azure Functions自定义身份验证中间件返回204状态码而不是401。

英文:

There are code issue in your middleware.

await _next(context); should be placed outside try...catch... and should be executed anyway.

My test code:

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            string id = context.Request.Query[&quot;id&quot;].ToString() ;
            if (id == &quot;1&quot;)
            {
                context.Response.StatusCode = 201;
            }
            else if (id == &quot;2&quot;)
            {
                context.Response.StatusCode = 401;
            }
        }
        catch (Exception)
        {
            context.Response.StatusCode = 401;
            throw;
        }
        // Do something...
        await _next(context);
    }

Test Result

.NET6 Azure Functions自定义身份验证中间件返回204状态码而不是401。

huangapple
  • 本文由 发表于 2023年1月6日 13:43:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75027347.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定