feat: allow users to logout
This commit is contained in:
@@ -9,6 +9,7 @@ internal static class AuthExtensions
|
||||
var authGroup = app.MapGroup(RouteGroupPrefix);
|
||||
|
||||
authGroup.MapLoginEndpoint();
|
||||
authGroup.MapLogoutEndpoint();
|
||||
|
||||
authGroup.MapRefreshEndpoint()
|
||||
.RequireAuthorization(Schemes.AllowExpiredTokens);
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
internal static class Endpoint
|
||||
{
|
||||
private const string Route = "/logout";
|
||||
|
||||
public static RouteHandlerBuilder MapLogoutEndpoint(this RouteGroupBuilder groupBuilder)
|
||||
{
|
||||
return groupBuilder.MapPost(Route, HandleAsync);
|
||||
}
|
||||
|
||||
private static async Task<IResult> HandleAsync(
|
||||
HttpContext httpContext,
|
||||
[FromServices] AppDbContext appDbContext,
|
||||
CancellationToken ct
|
||||
)
|
||||
{
|
||||
var userId = httpContext.GetUserId();
|
||||
var refreshToken = httpContext.GetRefreshTokenFromCookie();
|
||||
|
||||
var user = await appDbContext.Users
|
||||
.Include(u => u.RefreshTokens
|
||||
.Where(r => r.Token == refreshToken)
|
||||
)
|
||||
.Where(u => u.Id == userId)
|
||||
.SingleOrDefaultAsync(ct);
|
||||
|
||||
if (user is null || user.RefreshTokens.Any() is false)
|
||||
{
|
||||
return Results.Unauthorized();
|
||||
}
|
||||
|
||||
user.RefreshTokens.First().Revoke();
|
||||
await appDbContext.SaveChangesAsync(ct);
|
||||
|
||||
httpContext.ExpireRefreshTokenCookie();
|
||||
|
||||
return Results.NoContent();
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,21 @@ internal static class HttpContextExtensions
|
||||
);
|
||||
}
|
||||
|
||||
public static void ExpireRefreshTokenCookie(this HttpContext context)
|
||||
{
|
||||
context.Response.Cookies.Append(
|
||||
RefreshTokenCookieName,
|
||||
string.Empty,
|
||||
new CookieOptions
|
||||
{
|
||||
HttpOnly = true,
|
||||
Expires = DateTimeOffset.MinValue,
|
||||
SameSite = SameSiteMode.Strict,
|
||||
Secure = true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public static string GetRefreshTokenFromCookie(this HttpContext context)
|
||||
{
|
||||
return context.Request.Cookies[RefreshTokenCookieName] ?? string.Empty;
|
||||
|
||||
Reference in New Issue
Block a user