From 7e9b61783d1d8f0caf716be214af2ae24e6d5ea6 Mon Sep 17 00:00:00 2001 From: barzin144 Date: Mon, 29 Jun 2026 01:44:19 +0800 Subject: [PATCH] fix provider key for email login --- Service/JwtTokenService.cs | 169 +++++++++++++++++++++++++------------ 1 file changed, 116 insertions(+), 53 deletions(-) diff --git a/Service/JwtTokenService.cs b/Service/JwtTokenService.cs index 4e720bd..c866ded 100644 --- a/Service/JwtTokenService.cs +++ b/Service/JwtTokenService.cs @@ -1,9 +1,4 @@ -using Domain.Entities; -using Domain.Models; -using Domain.Services; -using Microsoft.Extensions.Options; -using Microsoft.IdentityModel.Tokens; -using System; +using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; @@ -11,6 +6,12 @@ using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; +using Domain.Entities; +using Domain.Enums; +using Domain.Models; +using Domain.Services; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; namespace Service { @@ -21,7 +22,11 @@ public class JwtTokenService : IJwtTokenService private readonly JwtOptions _jwtOptions; private readonly RSA _rsa; - public JwtTokenService(IUserService userService, ISecurityService securityService, IOptions jwtOptions) + public JwtTokenService( + IUserService userService, + ISecurityService securityService, + IOptions jwtOptions + ) { _userService = userService; _securityService = securityService; @@ -30,19 +35,29 @@ public JwtTokenService(IUserService userService, ISecurityService securityServic _rsa.ImportRSAPrivateKey(Convert.FromBase64String(_jwtOptions.PrivateKey), out _); } - public async Task AddUserTokenAsync(User user, string refreshTokenSerial, string accessToken, string refreshTokenSourceSerial) + public async Task AddUserTokenAsync( + User user, + string refreshTokenSerial, + string accessToken, + string refreshTokenSourceSerial + ) { var now = DateTimeOffset.UtcNow; var token = new Token { RefreshTokenIdHash = _securityService.GetSha256Hash(refreshTokenSerial), - RefreshTokenIdHashSource = string.IsNullOrWhiteSpace(refreshTokenSourceSerial) ? null : _securityService.GetSha256Hash(refreshTokenSourceSerial), + RefreshTokenIdHashSource = string.IsNullOrWhiteSpace(refreshTokenSourceSerial) + ? null + : _securityService.GetSha256Hash(refreshTokenSourceSerial), AccessTokenHash = _securityService.GetSha256Hash(accessToken), RefreshTokenExpiresDateTime = now.AddMinutes(_jwtOptions.RefreshTokenExpirationMinutes), - AccessTokenExpiresDateTime = now.AddMinutes(_jwtOptions.AccessTokenExpirationMinutes) + AccessTokenExpiresDateTime = now.AddMinutes(_jwtOptions.AccessTokenExpirationMinutes), }; - await _userService.DeleteTokensWithSameRefreshTokenSourceAsync(token.RefreshTokenIdHashSource, user.Id); + await _userService.DeleteTokensWithSameRefreshTokenSourceAsync( + token.RefreshTokenIdHashSource, + user.Id + ); await AddUserTokenAsync(token, user.Id); } @@ -55,7 +70,7 @@ public JwtTokensData CreateJwtTokens(User user) AccessToken = accessToken, Claims = claims, RefreshToken = refreshTokenValue, - RefreshTokenSerial = refreshTokenSerial + RefreshTokenSerial = refreshTokenSerial, }; } @@ -63,17 +78,38 @@ public JwtTokensData CreateJwtTokens(User user) { string jwtIssuer = _jwtOptions.Issuer; - List claims = [ - new Claim(JwtRegisteredClaimNames.Jti, _securityService.CreateCryptographicallySecureGuid().ToString(), ClaimValueTypes.String, jwtIssuer), - new Claim(JwtRegisteredClaimNames.Iss, jwtIssuer, ClaimValueTypes.String, jwtIssuer), - new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64, jwtIssuer), - new Claim(ClaimTypes.NameIdentifier, user.Id.ToString(), ClaimValueTypes.String, jwtIssuer), - new Claim(ClaimTypes.Name, user.Name, ClaimValueTypes.String, jwtIssuer), - new Claim(ClaimTypes.Email, user.Email, ClaimValueTypes.String, jwtIssuer), - new Claim(ClaimTypes.SerialNumber, user.SerialNumber, ClaimValueTypes.String, jwtIssuer), - new Claim(ClaimTypes.UserData, user.Id.ToString(), ClaimValueTypes.String, jwtIssuer), - new Claim("ProviderKey", user.ProviderKey, ClaimValueTypes.String, jwtIssuer), - new Claim("ProviderRefreshToken", user.ProviderRefreshToken, ClaimValueTypes.String, jwtIssuer) + List claims = + [ + new Claim( + JwtRegisteredClaimNames.Jti, + _securityService.CreateCryptographicallySecureGuid().ToString(), + ClaimValueTypes.String, + jwtIssuer + ), + new Claim(JwtRegisteredClaimNames.Iss, jwtIssuer, ClaimValueTypes.String, jwtIssuer), + new Claim( + JwtRegisteredClaimNames.Iat, + DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(), + ClaimValueTypes.Integer64, + jwtIssuer + ), + new Claim(ClaimTypes.NameIdentifier, user.Id.ToString(), ClaimValueTypes.String, jwtIssuer), + new Claim(ClaimTypes.Name, user.Name, ClaimValueTypes.String, jwtIssuer), + new Claim(ClaimTypes.Email, user.Email, ClaimValueTypes.String, jwtIssuer), + new Claim(ClaimTypes.SerialNumber, user.SerialNumber, ClaimValueTypes.String, jwtIssuer), + new Claim(ClaimTypes.UserData, user.Id.ToString(), ClaimValueTypes.String, jwtIssuer), + new Claim( + "ProviderKey", + user.Provider == Provider.Google ? user.ProviderKey : string.Empty, + ClaimValueTypes.String, + jwtIssuer + ), + new Claim( + "ProviderRefreshToken", + user.ProviderRefreshToken, + ClaimValueTypes.String, + jwtIssuer + ), ]; foreach (Role role in user.Roles) @@ -81,7 +117,10 @@ public JwtTokensData CreateJwtTokens(User user) claims.Add(new Claim(ClaimTypes.Role, role.Name, ClaimValueTypes.String, jwtIssuer)); } - SigningCredentials credentials = new SigningCredentials(new RsaSecurityKey(_rsa), SecurityAlgorithms.RsaSha256); + SigningCredentials credentials = new SigningCredentials( + new RsaSecurityKey(_rsa), + SecurityAlgorithms.RsaSha256 + ); DateTime now = DateTime.UtcNow; @@ -101,25 +140,42 @@ public JwtTokensData CreateJwtTokens(User user) { string jwtIssuer = _jwtOptions.Issuer; - string refreshTokenSerial = _securityService.CreateCryptographicallySecureGuid().ToString().Replace("-", ""); + string refreshTokenSerial = _securityService + .CreateCryptographicallySecureGuid() + .ToString() + .Replace("-", ""); List claims = new List - { - new Claim(JwtRegisteredClaimNames.Jti, _securityService.CreateCryptographicallySecureGuid().ToString(), ClaimValueTypes.String, jwtIssuer), - new Claim(JwtRegisteredClaimNames.Iss, jwtIssuer, ClaimValueTypes.String, jwtIssuer), - new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64, jwtIssuer), - new Claim(ClaimTypes.SerialNumber, refreshTokenSerial, ClaimValueTypes.String, jwtIssuer) - }; - SigningCredentials credentials = new SigningCredentials(new RsaSecurityKey(_rsa), SecurityAlgorithms.RsaSha256); + { + new Claim( + JwtRegisteredClaimNames.Jti, + _securityService.CreateCryptographicallySecureGuid().ToString(), + ClaimValueTypes.String, + jwtIssuer + ), + new Claim(JwtRegisteredClaimNames.Iss, jwtIssuer, ClaimValueTypes.String, jwtIssuer), + new Claim( + JwtRegisteredClaimNames.Iat, + DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(), + ClaimValueTypes.Integer64, + jwtIssuer + ), + new Claim(ClaimTypes.SerialNumber, refreshTokenSerial, ClaimValueTypes.String, jwtIssuer), + }; + SigningCredentials credentials = new SigningCredentials( + new RsaSecurityKey(_rsa), + SecurityAlgorithms.RsaSha256 + ); DateTime now = DateTime.UtcNow; JwtSecurityToken token = new JwtSecurityToken( - issuer: jwtIssuer, - audience: _jwtOptions.Audience, - claims: claims, - notBefore: now, - expires: now.AddMinutes(_jwtOptions.RefreshTokenExpirationMinutes), - signingCredentials: credentials); + issuer: jwtIssuer, + audience: _jwtOptions.Audience, + claims: claims, + notBefore: now, + expires: now.AddMinutes(_jwtOptions.RefreshTokenExpirationMinutes), + signingCredentials: credentials + ); string refreshTokenValue = new JwtSecurityTokenHandler().WriteToken(token); return (refreshTokenValue, refreshTokenSerial); @@ -151,18 +207,18 @@ public string GetRefreshTokenSerial(string refreshTokenValue) try { decodedRefreshTokenPrincipal = new JwtSecurityTokenHandler().ValidateToken( - refreshTokenValue, - new TokenValidationParameters - { - RequireExpirationTime = true, - ValidateIssuer = false, - ValidateAudience = false, - IssuerSigningKey = new RsaSecurityKey(_rsa), - ValidateIssuerSigningKey = true, - ValidateLifetime = true, - ClockSkew = TimeSpan.Zero - }, - out _ + refreshTokenValue, + new TokenValidationParameters + { + RequireExpirationTime = true, + ValidateIssuer = false, + ValidateAudience = false, + IssuerSigningKey = new RsaSecurityKey(_rsa), + ValidateIssuerSigningKey = true, + ValidateLifetime = true, + ClockSkew = TimeSpan.Zero, + }, + out _ ); } catch @@ -170,7 +226,9 @@ out _ throw; } - return decodedRefreshTokenPrincipal?.Claims?.FirstOrDefault(c => c.Type == ClaimTypes.SerialNumber)?.Value; + return decodedRefreshTokenPrincipal + ?.Claims?.FirstOrDefault(c => c.Type == ClaimTypes.SerialNumber) + ?.Value; } public async Task DeleteExpiredTokensAsync(string userId) @@ -194,14 +252,19 @@ public async Task RevokeUserBearerTokensAsync(string userId, string refreshToken if (!string.IsNullOrWhiteSpace(refreshTokenSerial)) { var refreshTokenIdHashSource = _securityService.GetSha256Hash(refreshTokenSerial); - await _userService.DeleteTokensWithSameRefreshTokenSourceAsync(refreshTokenIdHashSource, userId); + await _userService.DeleteTokensWithSameRefreshTokenSourceAsync( + refreshTokenIdHashSource, + userId + ); } } await DeleteExpiredTokensAsync(userId); } - public async Task<(Token token, User user)> FindUserAndTokenByRefreshTokenAsync(string refreshToken) + public async Task<(Token token, User user)> FindUserAndTokenByRefreshTokenAsync( + string refreshToken + ) { if (string.IsNullOrWhiteSpace(refreshToken)) {