fix: replace cookie-based Discord OAuth CSRF with server-side state store
- Replace __DiscordOAuthState cookie (blocked by third-party cookie policies) with in-memory DiscordOAuthStateStore singleton - State is created server-side and validated on callback, eliminating cross-site cookie transmission issues entirely - Removed CryptographicOperations dependency from Program.cs Bump version → 2.8.1 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
namespace GmRelay.Web.Services;
|
||||
|
||||
public sealed class DiscordOAuthStateStore(ILogger<DiscordOAuthStateStore> logger)
|
||||
{
|
||||
private readonly System.Collections.Concurrent.ConcurrentDictionary<string, DateTime> _states = new();
|
||||
|
||||
public string CreateState()
|
||||
{
|
||||
var state = Guid.NewGuid().ToString("N");
|
||||
_states[state] = DateTime.UtcNow.AddMinutes(5);
|
||||
logger.LogDebug("Discord OAuth state created: {State}", state);
|
||||
return state;
|
||||
}
|
||||
|
||||
public bool ValidateAndRemove(string state)
|
||||
{
|
||||
if (!_states.TryRemove(state, out var expiresAt))
|
||||
{
|
||||
logger.LogWarning("Discord OAuth state not found or already used: {State}", state);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DateTime.UtcNow > expiresAt)
|
||||
{
|
||||
logger.LogWarning("Discord OAuth state expired: {State}", state);
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.LogDebug("Discord OAuth state validated: {State}", state);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user