refactor: rename cancellation to cancellationToken
This commit is contained in:
@ -29,14 +29,14 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
|
||||
private static string GetFirstAuthCacheKey(string fingerprint) => $"{fingerprint}_auth_token_first";
|
||||
private static string GetAttemptFailedCountKey(string fingerprint) => $"{fingerprint}_login_failed";
|
||||
|
||||
private Task StoreAuthTokenInCache(AuthToken data, CancellationToken cancellation) =>
|
||||
private Task StoreAuthTokenInCache(AuthToken data, CancellationToken cancellationToken) =>
|
||||
cache.SetAsync(
|
||||
GetAuthCacheKey(data.Fingerprint),
|
||||
JsonSerializer.SerializeToUtf8Bytes(data),
|
||||
slidingExpiration: Lifetime,
|
||||
cancellationToken: cancellation);
|
||||
cancellationToken: cancellationToken);
|
||||
|
||||
private Task StoreFirstAuthTokenInCache(User data, RequestContextInfo requestContext, CancellationToken cancellation) =>
|
||||
private Task StoreFirstAuthTokenInCache(User data, RequestContextInfo requestContext, CancellationToken cancellationToken) =>
|
||||
cache.SetAsync(
|
||||
GetFirstAuthCacheKey(requestContext.Fingerprint),
|
||||
JsonSerializer.SerializeToUtf8Bytes(new FirstAuthToken(requestContext)
|
||||
@ -46,14 +46,14 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
|
||||
TwoFactorAuthenticator = data.TwoFactorAuthenticator
|
||||
}),
|
||||
slidingExpiration: LifetimeFirstAuth,
|
||||
cancellationToken: cancellation);
|
||||
cancellationToken: cancellationToken);
|
||||
|
||||
private Task RevokeAccessToken(string token) =>
|
||||
revokedToken.AddTokenToRevokedAsync(token, accessTokenService.GetExpireDateTime(token));
|
||||
|
||||
private async Task RecordFailedLoginAttempt(string fingerprint, string userId, CancellationToken cancellation)
|
||||
private async Task RecordFailedLoginAttempt(string fingerprint, string userId, CancellationToken cancellationToken)
|
||||
{
|
||||
var failedLoginAttemptsCount = await cache.GetAsync<int?>(GetAttemptFailedCountKey(fingerprint), cancellation) ?? 1;
|
||||
var failedLoginAttemptsCount = await cache.GetAsync<int?>(GetAttemptFailedCountKey(fingerprint), cancellationToken) ?? 1;
|
||||
var failedLoginCacheExpiration = TimeSpan.FromHours(1);
|
||||
|
||||
if (failedLoginAttemptsCount > 5)
|
||||
@ -74,30 +74,30 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
|
||||
failedLoginAttemptsCount);
|
||||
|
||||
await cache.SetAsync(GetAttemptFailedCountKey(fingerprint), failedLoginAttemptsCount + 1,
|
||||
slidingExpiration: failedLoginCacheExpiration, cancellationToken: cancellation);
|
||||
slidingExpiration: failedLoginCacheExpiration, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
private Task ResetFailedLoginAttempts(string fingerprint, CancellationToken cancellation) =>
|
||||
cache.RemoveAsync(GetAttemptFailedCountKey(fingerprint), cancellation);
|
||||
private Task ResetFailedLoginAttempts(string fingerprint, CancellationToken cancellationToken) =>
|
||||
cache.RemoveAsync(GetAttemptFailedCountKey(fingerprint), cancellationToken);
|
||||
|
||||
private async Task VerifyUserOrThrowError(RequestContextInfo requestContext, User user, string password, string username,
|
||||
CancellationToken cancellation = default)
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
if ((user.Email.Equals(username, StringComparison.OrdinalIgnoreCase) ||
|
||||
user.Username.Equals(username, StringComparison.OrdinalIgnoreCase)) &&
|
||||
passwordService.VerifyPassword(password, user.Salt, user.PasswordHash))
|
||||
{
|
||||
await ResetFailedLoginAttempts(requestContext.Fingerprint, cancellation);
|
||||
await ResetFailedLoginAttempts(requestContext.Fingerprint, cancellationToken);
|
||||
return;
|
||||
}
|
||||
|
||||
await RecordFailedLoginAttempt(requestContext.Fingerprint, user.Id, cancellation);
|
||||
await RecordFailedLoginAttempt(requestContext.Fingerprint, user.Id, cancellationToken);
|
||||
|
||||
throw new SecurityException("Authentication failed. Please check your credentials.");
|
||||
}
|
||||
|
||||
private async Task GenerateAuthTokensAsync(CookieOptions cookieOptions, HttpContext context,
|
||||
RequestContextInfo requestContext, string userId, CancellationToken cancellation = default)
|
||||
RequestContextInfo requestContext, string userId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var refreshToken = GenerateRefreshToken();
|
||||
var (token, expireIn) = GenerateAccessToken(userId);
|
||||
@ -110,7 +110,7 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
|
||||
AccessToken = token
|
||||
};
|
||||
|
||||
await StoreAuthTokenInCache(authToken, cancellation);
|
||||
await StoreAuthTokenInCache(authToken, cancellationToken);
|
||||
cookieOptions.SetCookie(context, CookieNames.AccessToken, authToken.AccessToken, expireIn);
|
||||
cookieOptions.SetCookie(context, CookieNames.RefreshToken, authToken.RefreshToken, DateTime.UtcNow.Add(Lifetime));
|
||||
|
||||
@ -121,11 +121,11 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
|
||||
}
|
||||
|
||||
public async Task<bool> LoginAsync(CookieOptions cookieOptions, HttpContext context, TwoFactorAuthenticator authenticator, string code,
|
||||
CancellationToken cancellation = default)
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var requestContext = new RequestContextInfo(context, cookieOptions);
|
||||
|
||||
var firstTokenAuth = await cache.GetAsync<FirstAuthToken?>(GetFirstAuthCacheKey(requestContext.Fingerprint), cancellationToken: cancellation);
|
||||
var firstTokenAuth = await cache.GetAsync<FirstAuthToken?>(GetFirstAuthCacheKey(requestContext.Fingerprint), cancellationToken: cancellationToken);
|
||||
|
||||
if (firstTokenAuth == null || authenticator != firstTokenAuth.TwoFactorAuthenticator)
|
||||
throw new SecurityException("Session expired. Please log in again.");
|
||||
@ -147,35 +147,35 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
|
||||
|
||||
if (!totp.VerifyToken(code))
|
||||
{
|
||||
await RecordFailedLoginAttempt(requestContext.Fingerprint, firstTokenAuth.UserId, cancellation);
|
||||
await RecordFailedLoginAttempt(requestContext.Fingerprint, firstTokenAuth.UserId, cancellationToken);
|
||||
throw new SecurityException("Invalid verification code. Please try again.");
|
||||
}
|
||||
|
||||
await ResetFailedLoginAttempts(requestContext.Fingerprint, cancellation);
|
||||
await ResetFailedLoginAttempts(requestContext.Fingerprint, cancellationToken);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Unsupported authorization method.");
|
||||
}
|
||||
|
||||
await GenerateAuthTokensAsync(cookieOptions, context, requestContext, firstTokenAuth.UserId, cancellation);
|
||||
await GenerateAuthTokensAsync(cookieOptions, context, requestContext, firstTokenAuth.UserId, cancellationToken);
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<TwoFactorAuthenticator> LoginAsync(CookieOptions cookieOptions,
|
||||
HttpContext context,
|
||||
User user,
|
||||
CancellationToken cancellation = default)
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var requestContext = new RequestContextInfo(context, cookieOptions);
|
||||
|
||||
if (user.TwoFactorAuthenticator == TwoFactorAuthenticator.None)
|
||||
{
|
||||
await GenerateAuthTokensAsync(cookieOptions, context, requestContext, user.Id, cancellation);
|
||||
await GenerateAuthTokensAsync(cookieOptions, context, requestContext, user.Id, cancellationToken);
|
||||
return TwoFactorAuthenticator.None;
|
||||
}
|
||||
|
||||
await StoreFirstAuthTokenInCache(user, requestContext, cancellation);
|
||||
await StoreFirstAuthTokenInCache(user, requestContext, cancellationToken);
|
||||
|
||||
return user.TwoFactorAuthenticator;
|
||||
}
|
||||
@ -201,20 +201,20 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
|
||||
User user,
|
||||
string password,
|
||||
string username,
|
||||
CancellationToken cancellation = default)
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var requestContext = new RequestContextInfo(context, cookieOptions);
|
||||
username = username.Trim();
|
||||
await VerifyUserOrThrowError(requestContext, user, password, username, cancellation);
|
||||
await VerifyUserOrThrowError(requestContext, user, password, username, cancellationToken);
|
||||
|
||||
return await LoginAsync(cookieOptions, context, user, cancellation);
|
||||
return await LoginAsync(cookieOptions, context, user, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task RefreshTokenAsync(CookieOptions cookieOptions, HttpContext context, CancellationToken cancellation = default)
|
||||
public async Task RefreshTokenAsync(CookieOptions cookieOptions, HttpContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
const string defaultMessageError = "The session time has expired";
|
||||
var requestContext = new RequestContextInfo(context, cookieOptions);
|
||||
var authToken = await cache.GetAsync<AuthToken>(GetAuthCacheKey(requestContext.Fingerprint), cancellation) ??
|
||||
var authToken = await cache.GetAsync<AuthToken>(GetAuthCacheKey(requestContext.Fingerprint), cancellationToken) ??
|
||||
throw new SecurityException(defaultMessageError);
|
||||
|
||||
if (authToken.RefreshToken != requestContext.RefreshToken ||
|
||||
@ -222,7 +222,7 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
|
||||
authToken.Ip != requestContext.Ip)
|
||||
{
|
||||
await RevokeAccessToken(authToken.AccessToken);
|
||||
await cache.RemoveAsync(GetAuthCacheKey(requestContext.Fingerprint), cancellation);
|
||||
await cache.RemoveAsync(GetAuthCacheKey(requestContext.Fingerprint), cancellationToken);
|
||||
cookieOptions.DropCookie(context, CookieNames.AccessToken);
|
||||
cookieOptions.DropCookie(context, CookieNames.RefreshToken);
|
||||
|
||||
@ -274,24 +274,24 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
|
||||
authToken.AccessToken = token;
|
||||
authToken.RefreshToken = newRefreshToken;
|
||||
|
||||
await StoreAuthTokenInCache(authToken, cancellation);
|
||||
await StoreAuthTokenInCache(authToken, cancellationToken);
|
||||
cookieOptions.SetCookie(context, CookieNames.AccessToken, authToken.AccessToken, expireIn);
|
||||
cookieOptions.SetCookie(context, CookieNames.RefreshToken, authToken.RefreshToken, DateTime.UtcNow.Add(Lifetime));
|
||||
}
|
||||
|
||||
public async Task LogoutAsync(CookieOptions cookieOptions, HttpContext context, CancellationToken cancellation = default)
|
||||
public async Task LogoutAsync(CookieOptions cookieOptions, HttpContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var requestContext = new RequestContextInfo(context, cookieOptions);
|
||||
|
||||
cookieOptions.DropCookie(context, CookieNames.AccessToken);
|
||||
cookieOptions.DropCookie(context, CookieNames.RefreshToken);
|
||||
|
||||
var authTokenStruct = await cache.GetAsync<AuthToken>(GetAuthCacheKey(requestContext.Fingerprint), cancellation);
|
||||
var authTokenStruct = await cache.GetAsync<AuthToken>(GetAuthCacheKey(requestContext.Fingerprint), cancellationToken);
|
||||
|
||||
if (authTokenStruct == null)
|
||||
return;
|
||||
|
||||
await RevokeAccessToken(authTokenStruct.AccessToken);
|
||||
await cache.RemoveAsync(requestContext.Fingerprint, cancellation);
|
||||
await cache.RemoveAsync(requestContext.Fingerprint, cancellationToken);
|
||||
}
|
||||
}
|
@ -58,7 +58,7 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
};
|
||||
|
||||
private static async Task<OAuthTokenResponse?> ExchangeCodeForTokensAsync(string requestUri, string redirectUrl, string code,
|
||||
string clientId, string secret, CancellationToken cancellation)
|
||||
string clientId, string secret, CancellationToken cancellationToken)
|
||||
{
|
||||
var tokenRequest = new HttpRequestMessage(HttpMethod.Post, requestUri)
|
||||
{
|
||||
@ -75,8 +75,8 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
using var httpClient = new HttpClient();
|
||||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("MireaSchedule/1.0 (Winsomnia)");
|
||||
|
||||
var response = await httpClient.SendAsync(tokenRequest, cancellation);
|
||||
var data = await response.Content.ReadAsStringAsync(cancellation);
|
||||
var response = await httpClient.SendAsync(tokenRequest, cancellationToken);
|
||||
var data = await response.Content.ReadAsStringAsync(cancellationToken);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
throw new HttpRequestException(data);
|
||||
@ -85,7 +85,7 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
}
|
||||
|
||||
private static async Task<OAuthUser?> GetUserProfileAsync(string requestUri, string authHeader, string accessToken, OAuthProvider provider,
|
||||
CancellationToken cancellation)
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
|
||||
|
||||
@ -97,8 +97,8 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
using var httpClient = new HttpClient();
|
||||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("MireaSchedule/1.0 (Winsomnia)");
|
||||
|
||||
var response = await httpClient.SendAsync(request, cancellation);
|
||||
var data = await response.Content.ReadAsStringAsync(cancellation);
|
||||
var response = await httpClient.SendAsync(request, cancellationToken);
|
||||
var data = await response.Content.ReadAsStringAsync(cancellationToken);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
throw new HttpRequestException(data);
|
||||
@ -167,12 +167,12 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
}
|
||||
}
|
||||
|
||||
private Task StoreOAuthUserInCache(string key, OAuthUserExtension data, CancellationToken cancellation) =>
|
||||
private Task StoreOAuthUserInCache(string key, OAuthUserExtension data, CancellationToken cancellationToken) =>
|
||||
cache.SetAsync(
|
||||
key,
|
||||
JsonSerializer.SerializeToUtf8Bytes(data),
|
||||
absoluteExpirationRelativeToNow: TimeSpan.FromMinutes(15),
|
||||
cancellationToken: cancellation);
|
||||
cancellationToken: cancellationToken);
|
||||
|
||||
|
||||
public Uri GetProviderRedirect(CookieOptions cookieOptions, HttpContext context, string redirectUri,
|
||||
@ -209,7 +209,7 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
[.. providers.Select(x => (x.Key, new Uri(redirectUri.TrimEnd('/') + "/?provider=" + (int)x.Key)))];
|
||||
|
||||
public async Task<LoginOAuth> LoginOAuth(CookieOptions cookieOptions, HttpContext context,
|
||||
string redirectUrl, string code, string state, CancellationToken cancellation = default)
|
||||
string redirectUrl, string code, string state, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = new LoginOAuth()
|
||||
{
|
||||
@ -226,7 +226,7 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
{
|
||||
Message = result.ErrorMessage,
|
||||
Provider = null
|
||||
}, cancellation);
|
||||
}, cancellationToken);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -251,7 +251,7 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
result.ErrorMessage = "Invalid authorization request. Please try again later.";
|
||||
cacheData.Message = result.ErrorMessage;
|
||||
|
||||
await StoreOAuthUserInCache(result.Token, cacheData, cancellation);
|
||||
await StoreOAuthUserInCache(result.Token, cacheData, cancellationToken);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -271,7 +271,7 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
checksum
|
||||
);
|
||||
|
||||
await StoreOAuthUserInCache(result.Token, cacheData, cancellation);
|
||||
await StoreOAuthUserInCache(result.Token, cacheData, cancellationToken);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -280,7 +280,7 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
try
|
||||
{
|
||||
accessToken = await ExchangeCodeForTokensAsync(currentProviderStruct.TokenUrl, redirectUrl, code, providerInfo.ClientId,
|
||||
providerInfo.Secret, cancellation);
|
||||
providerInfo.Secret, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -288,7 +288,7 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
payload.Provider,
|
||||
checksum);
|
||||
|
||||
await StoreOAuthUserInCache(result.Token, cacheData, cancellation);
|
||||
await StoreOAuthUserInCache(result.Token, cacheData, cancellationToken);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -300,14 +300,14 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
try
|
||||
{
|
||||
user = await GetUserProfileAsync(currentProviderStruct.UserInfoUrl, currentProviderStruct.AuthHeader, accessToken.AccessToken,
|
||||
payload.Provider, cancellation);
|
||||
payload.Provider, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogWarning(ex, "Failed to retrieve user information from provider {Provider}",
|
||||
payload.Provider);
|
||||
|
||||
await StoreOAuthUserInCache(result.Token, cacheData, cancellation);
|
||||
await StoreOAuthUserInCache(result.Token, cacheData, cancellationToken);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -323,24 +323,24 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
IsSuccess = true,
|
||||
User = user,
|
||||
Provider = payload.Provider
|
||||
}, cancellation);
|
||||
}, cancellationToken);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<(OAuthUser? User, string? Message, bool IsSuccess, OAuthProvider? Provider)>
|
||||
GetOAuthUser(CookieOptions cookieOptions, HttpContext context, string token, CancellationToken cancellation = default)
|
||||
GetOAuthUser(CookieOptions cookieOptions, HttpContext context, string token, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var requestInfo = new RequestContextInfo(context, cookieOptions);
|
||||
|
||||
var result = await cache.GetAsync<OAuthUserExtension>(token, cancellation);
|
||||
var result = await cache.GetAsync<OAuthUserExtension>(token, cancellationToken);
|
||||
var tokenFailedKey = $"{requestInfo.Fingerprint}_oauth_token_failed";
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
var failedTokenAttemptsCount = await cache.GetAsync<int?>(
|
||||
tokenFailedKey,
|
||||
cancellation) ?? 1;
|
||||
cancellationToken) ?? 1;
|
||||
|
||||
var failedTokenCacheExpiration = TimeSpan.FromHours(1);
|
||||
|
||||
@ -364,7 +364,7 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
await cache.SetAsync(tokenFailedKey,
|
||||
failedTokenAttemptsCount + 1,
|
||||
slidingExpiration: failedTokenCacheExpiration,
|
||||
cancellationToken: cancellation);
|
||||
cancellationToken: cancellationToken);
|
||||
|
||||
return (null, "Invalid or expired token.", false, null);
|
||||
}
|
||||
@ -406,18 +406,18 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
|
||||
result.Ip,
|
||||
requestInfo.Ip);
|
||||
|
||||
await cache.RemoveAsync(token, cancellation);
|
||||
await cache.RemoveAsync(token, cancellationToken);
|
||||
|
||||
return (null, "Invalid or expired token.", false, null);
|
||||
}
|
||||
|
||||
await cache.RemoveAsync(tokenFailedKey, cancellation);
|
||||
await cache.RemoveAsync(tokenFailedKey, cancellationToken);
|
||||
|
||||
result.Ip = requestInfo.Ip;
|
||||
result.UserAgent = requestInfo.UserAgent;
|
||||
result.Fingerprint = requestInfo.Fingerprint;
|
||||
|
||||
await StoreOAuthUserInCache(token, result, cancellation);
|
||||
await StoreOAuthUserInCache(token, result, cancellationToken);
|
||||
|
||||
return (result.User, result.Message, result.IsSuccess, result.Provider);
|
||||
}
|
||||
|
Reference in New Issue
Block a user