From 9d1915fc81fc412f657883840bf0bec22d817209 Mon Sep 17 00:00:00 2001 From: Gradyn Wursten Date: Sat, 28 Oct 2023 09:15:43 -0600 Subject: [PATCH] insert token ID into JWTs --- JournalyApiV2/Data/JournalyDbContext.cs | 2 +- JournalyApiV2/Models/RefreshToken.cs | 7 +++++++ JournalyApiV2/Services/BLL/AuthService.cs | 15 ++++++++------ JournalyApiV2/Services/DAL/AuthDbService.cs | 21 +++++++++++++------- JournalyApiV2/Services/DAL/IAuthDbService.cs | 8 +++++--- 5 files changed, 36 insertions(+), 17 deletions(-) create mode 100644 JournalyApiV2/Models/RefreshToken.cs diff --git a/JournalyApiV2/Data/JournalyDbContext.cs b/JournalyApiV2/Data/JournalyDbContext.cs index df7cc97..f26e05f 100644 --- a/JournalyApiV2/Data/JournalyDbContext.cs +++ b/JournalyApiV2/Data/JournalyDbContext.cs @@ -34,7 +34,7 @@ public class JournalyDbContext : IdentityDbContext public DbSet RecordTypes { get; set; } public DbSet MedicationInstances { get; set; } public DbSet MedStatuses { get; set; } - public DbSet RefreshTokens { get; set; } + public DbSet RefreshTokens { get; set; } public JournalyDbContext(IConfiguration config) { diff --git a/JournalyApiV2/Models/RefreshToken.cs b/JournalyApiV2/Models/RefreshToken.cs new file mode 100644 index 0000000..c992f70 --- /dev/null +++ b/JournalyApiV2/Models/RefreshToken.cs @@ -0,0 +1,7 @@ +namespace JournalyApiV2.Models; + +public class RefreshToken +{ + public int TokenId { get; set; } + public string Token { get; set; } +} \ No newline at end of file diff --git a/JournalyApiV2/Services/BLL/AuthService.cs b/JournalyApiV2/Services/BLL/AuthService.cs index 22f7f66..514a318 100644 --- a/JournalyApiV2/Services/BLL/AuthService.cs +++ b/JournalyApiV2/Services/BLL/AuthService.cs @@ -30,7 +30,7 @@ public AuthService(UserManager userManager, IConfiguration config, _authDbService = authDbService; } - private string GenerateJwtToken(string userId, string email, string givenName, string familyName) + private string GenerateJwtToken(string userId, string email, string givenName, string familyName, int tokenId) { var claims = new List { @@ -38,7 +38,8 @@ private string GenerateJwtToken(string userId, string email, string givenName, s new Claim(JwtRegisteredClaimNames.Email, email), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(JwtRegisteredClaimNames.GivenName, givenName), - new Claim(JwtRegisteredClaimNames.FamilyName, familyName) + new Claim(JwtRegisteredClaimNames.FamilyName, familyName), + new Claim("TokenId", tokenId.ToString()) }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Identity:Key"])); @@ -66,11 +67,13 @@ public async Task SignIn(string email, string password) { throw new Exception("Email and password is valid, but no user found"); } + + var refreshToken = await _authDbService.NewRefreshTokenAsync(Guid.Parse(user.Id)); return new SignInResponse { - Token = GenerateJwtToken(user.Id, email, user.FirstName, user.LastName), + Token = GenerateJwtToken(user.Id, email, user.FirstName, user.LastName, refreshToken.TokenId), ExpiresIn = _config.GetValue("Identity:ExpireSeconds"), - RefreshToken = await _authDbService.NewRefreshTokenAsync(Guid.Parse(user.Id)) + RefreshToken = refreshToken.Token }; } else @@ -109,9 +112,9 @@ public async Task RefreshToken(string refreshToken) if (newToken == null) throw new Exception("Failed to refresh token"); return new SignInResponse { - RefreshToken = newToken, + RefreshToken = newToken.Token, ExpiresIn = _config.GetValue("Identity:ExpireSeconds"), - Token = GenerateJwtToken(user.Id, user.Email, user.FirstName, user.LastName) + Token = GenerateJwtToken(user.Id, user.Email, user.FirstName, user.LastName, newToken.TokenId) }; } } \ No newline at end of file diff --git a/JournalyApiV2/Services/DAL/AuthDbService.cs b/JournalyApiV2/Services/DAL/AuthDbService.cs index c9b5cd4..380472a 100644 --- a/JournalyApiV2/Services/DAL/AuthDbService.cs +++ b/JournalyApiV2/Services/DAL/AuthDbService.cs @@ -22,34 +22,41 @@ private static string GenerateSecureOpaqueToken() return Convert.ToBase64String(byteArr); } - public async Task ExchangeRefreshTokenAsync(string token) + public async Task ExchangeRefreshTokenAsync(string token) { await using var db = _db.Journaly(); var oldToken = await db.RefreshTokens.SingleOrDefaultAsync(x => x.Token == token); if (oldToken == null) return null; db.Remove(oldToken); var newToken = GenerateSecureOpaqueToken(); - db.RefreshTokens.Add(new RefreshToken + var result = db.RefreshTokens.Add(new RefreshToken { Token = newToken, UserId = oldToken.UserId }); await db.SaveChangesAsync(); - return newToken; + return new Models.RefreshToken + { + Token = newToken, + TokenId = result.Entity.Id + }; } - public async Task NewRefreshTokenAsync(Guid user) + public async Task NewRefreshTokenAsync(Guid user) { await using var db = _db.Journaly(); var newToken = GenerateSecureOpaqueToken(); - db.RefreshTokens.Add(new RefreshToken + var result = db.RefreshTokens.Add(new RefreshToken { Token = newToken, UserId = user }); await db.SaveChangesAsync(); - return newToken; - } + return new Models.RefreshToken + { + Token = newToken, + TokenId = result.Entity.Id + }; } public async Task LookupRefreshTokenAsync(string token) { diff --git a/JournalyApiV2/Services/DAL/IAuthDbService.cs b/JournalyApiV2/Services/DAL/IAuthDbService.cs index 8941704..4c1f0ac 100644 --- a/JournalyApiV2/Services/DAL/IAuthDbService.cs +++ b/JournalyApiV2/Services/DAL/IAuthDbService.cs @@ -1,8 +1,10 @@ -namespace JournalyApiV2.Services.DAL; +using JournalyApiV2.Models; + +namespace JournalyApiV2.Services.DAL; public interface IAuthDbService { - Task ExchangeRefreshTokenAsync(string token); + Task ExchangeRefreshTokenAsync(string token); Task LookupRefreshTokenAsync(string token); - Task NewRefreshTokenAsync(Guid user); + Task NewRefreshTokenAsync(Guid user); } \ No newline at end of file