英文:
.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<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");
}
}
}
答案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("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;
答案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);
}
测试结果
英文:
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["id"].ToString() ;
if (id == "1")
{
context.Response.StatusCode = 201;
}
else if (id == "2")
{
context.Response.StatusCode = 401;
}
}
catch (Exception)
{
context.Response.StatusCode = 401;
throw;
}
// Do something...
await _next(context);
}
Test Result
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论