| | | 1 | | using Anichron.API.Security; |
| | | 2 | | |
| | | 3 | | namespace Anichron.API.Infrastructure; |
| | | 4 | | |
| | 9 | 5 | | internal sealed class MustChangePasswordMiddleware(RequestDelegate next) |
| | | 6 | | { |
| | 1 | 7 | | private static readonly (string Method, PathString Path)[] exemptRoutes = |
| | 1 | 8 | | [ |
| | 1 | 9 | | (HttpMethods.Get, new(ApiPaths.Users.MePath)), |
| | 1 | 10 | | (HttpMethods.Post, new(ApiPaths.Users.ChangePasswordPath)), |
| | 1 | 11 | | (HttpMethods.Post, new(ApiPaths.Auth.LogoutPath)), |
| | 1 | 12 | | ]; |
| | | 13 | | |
| | | 14 | | public async Task InvokeAsync(HttpContext context) |
| | 9 | 15 | | { |
| | 9 | 16 | | if (context.User.Identity?.IsAuthenticated == true |
| | 9 | 17 | | && context.User.HasClaim(AppClaimTypes.MustChangePassword, "true") |
| | 9 | 18 | | && !IsExemptRequest(context.Request)) |
| | 3 | 19 | | { |
| | 3 | 20 | | context.Response.StatusCode = StatusCodes.Status403Forbidden; |
| | 3 | 21 | | await context.Response.WriteAsJsonAsync( |
| | 3 | 22 | | new { error = AuthMessages.MustChangePassword }, context.RequestAborted); |
| | 3 | 23 | | return; |
| | | 24 | | } |
| | | 25 | | |
| | 6 | 26 | | await next(context); |
| | 9 | 27 | | } |
| | | 28 | | |
| | | 29 | | private static bool IsExemptRequest(HttpRequest request) |
| | 6 | 30 | | => exemptRoutes.Any(e => e.Method == request.Method && e.Path == request.Path); |
| | | 31 | | } |