Skip to content

Commit

Permalink
Add logout endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
LucHeart committed Nov 7, 2024
1 parent b10a986 commit 4df7f86
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 2 deletions.
55 changes: 55 additions & 0 deletions API/Controller/Account/Authenticated/Logout.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using Microsoft.AspNetCore.Mvc;
using OpenShock.Common.Authentication.Attributes;
using OpenShock.Common.Authentication.Services;
using OpenShock.Common.Problems;

namespace OpenShock.API.Controller.Account.Authenticated;

public sealed partial class AuthenticatedAccountController
{
[HttpDelete("logout")]
[UserSessionOnly]
[ProducesSlimSuccess]
public async Task<IActionResult> Logout(
[FromServices] IUserReferenceService userReferenceService,
[FromServices] ApiConfig apiConfig)
{
var x = userReferenceService.AuthReference;

if (x == null) throw new Exception("This should not be reachable due to AuthenticatedSession requirement");
if (!x.Value.IsT0) throw new Exception("This should not be reachable due to the [UserSessionOnly] attribute");

var session = x.Value.AsT0;

await _sessionService.DeleteSession(session);

var cookieDomainToUse = apiConfig.Frontend.CookieDomain.Split(',').FirstOrDefault(domain => Request.Headers.Host.ToString().EndsWith(domain, StringComparison.OrdinalIgnoreCase));
if (cookieDomainToUse != null)
{
HttpContext.Response.Cookies.Append("openShockSession", string.Empty, new CookieOptions
{
Expires = DateTimeOffset.FromUnixTimeSeconds(0),
Secure = true,
HttpOnly = true,
SameSite = SameSiteMode.Strict,
Domain = "." + cookieDomainToUse
});
}
else // Fallback to all domains
{
foreach (var stringValue in apiConfig.Frontend.CookieDomain.Split(','))
{
HttpContext.Response.Cookies.Append("openShockSession", string.Empty, new CookieOptions
{
Expires = DateTimeOffset.FromUnixTimeSeconds(0),
Secure = true,
HttpOnly = true,
SameSite = SameSiteMode.Strict,
Domain = "." + stringValue
});
}
}

return RespondSlimSuccess();
}
}
10 changes: 9 additions & 1 deletion API/Controller/Account/Authenticated/_ApiController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Mvc;
using OpenShock.API.Services.Account;
using OpenShock.API.Services.Session;
using OpenShock.Common.Authentication.Attributes;
using OpenShock.Common.Authentication.ControllerBase;
using OpenShock.Common.OpenShockDb;
Expand All @@ -21,12 +22,19 @@ public sealed partial class AuthenticatedAccountController : AuthenticatedSessio
private readonly IRedisConnectionProvider _redis;
private readonly ILogger<AuthenticatedAccountController> _logger;
private readonly IAccountService _accountService;
private readonly ISessionService _sessionService;

public AuthenticatedAccountController(OpenShockContext db, IRedisConnectionProvider redis, ILogger<AuthenticatedAccountController> logger, IAccountService accountService)
public AuthenticatedAccountController(
OpenShockContext db,
IRedisConnectionProvider redis,
ILogger<AuthenticatedAccountController> logger,
IAccountService accountService,
ISessionService sessionService)
{
_db = db;
_redis = redis;
_logger = logger;
_accountService = accountService;
_sessionService = sessionService;
}
}
3 changes: 2 additions & 1 deletion API/Services/Session/ISessionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ public interface ISessionService
{
public Task<IEnumerable<LoginSession>> ListSessions(Guid userId);

public Task<LoginSession?> GetSession(Guid userId);
public Task<LoginSession?> GetSession(Guid sessionId);

public Task<bool> DeleteSession(Guid sessionId);
public Task DeleteSession(LoginSession loginSession);
}
9 changes: 9 additions & 0 deletions API/Services/Session/SessionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ public async Task<IEnumerable<LoginSession>> ListSessions(Guid userId)
.FirstOrDefaultAsync();
}

public async Task<bool> DeleteSession(Guid sessionId)
{
var session = await GetSession(sessionId);
if (session == null) return false;

await _loginSessions.DeleteAsync(session);
return true;
}

public async Task DeleteSession(LoginSession loginSession)
{
await _loginSessions.DeleteAsync(loginSession);
Expand Down

0 comments on commit 4df7f86

Please sign in to comment.