sec: to establish the ownership of the token for the first one who received it

This commit is contained in:
Polianin Nikita 2024-12-28 08:30:56 +03:00
parent e79ddf220f
commit 6358410f18
2 changed files with 35 additions and 2 deletions

View File

@ -5,5 +5,8 @@ internal class OAuthUserExtension
public string? Message { get; set; } public string? Message { get; set; }
public bool IsSuccess { get; set; } public bool IsSuccess { get; set; }
public required OAuthProvider? Provider { get; set; } public required OAuthProvider? Provider { get; set; }
public string? UserAgent { get; set; } = null;
public string? Ip { get; set; } = null;
public string? Fingerprint { get; set; } = null;
public OAuthUser? User { get; set; } public OAuthUser? User { get; set; }
} }

View File

@ -369,8 +369,6 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
return (null, "Invalid or expired token.", false, null); return (null, "Invalid or expired token.", false, null);
} }
await cache.RemoveAsync(tokenFailedKey, cancellation);
const string log = "Cache data retrieved for token: {Token}. Fingerprint: {Fingerprint}."; const string log = "Cache data retrieved for token: {Token}. Fingerprint: {Fingerprint}.";
if (result.User != null) if (result.User != null)
@ -387,6 +385,38 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
else else
logger.LogInformation(log, token, requestInfo.Fingerprint); logger.LogInformation(log, token, requestInfo.Fingerprint);
if ((!string.IsNullOrEmpty(result.Fingerprint) &&
result.Fingerprint != requestInfo.Fingerprint) ||
(!string.IsNullOrEmpty(result.UserAgent) &&
result.UserAgent != requestInfo.UserAgent &&
!string.IsNullOrEmpty(result.Ip)) &&
result.Ip != requestInfo.Ip)
{
logger.LogWarning(
"Potential token compromise detected. " +
"Token {Token} has been used from different location. " +
"Fingerprint: {ExpectedFingerprint} -> {ProvidedFingerprint}, " +
"UserAgent: {ExpectedUserAgent} -> {ProvidedUserAgent}, " +
"Ip: {ExpectedUserIp} -> {ProvidedIp}",
token,
result.Fingerprint,
requestInfo.Fingerprint,
result.UserAgent,
requestInfo.UserAgent,
result.Ip,
requestInfo.Ip);
await cache.RemoveAsync(token, cancellation);
return (null, "Invalid or expired token.", false, null);
}
await cache.RemoveAsync(tokenFailedKey, cancellation);
result.Ip = requestInfo.Ip;
result.UserAgent = requestInfo.UserAgent;
result.Fingerprint = requestInfo.Fingerprint;
return (result.User, result.Message, result.IsSuccess, result.Provider); return (result.User, result.Message, result.IsSuccess, result.Provider);
} }
} }