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