Compare commits

...

2 Commits

5 changed files with 48 additions and 14 deletions

View File

@ -4,8 +4,14 @@
{ {
public string? Key { get; set; } public string? Key { get; set; }
public string? Issuer { get; set; } public string? Issuer { get; set; }
public string? Audience { get; set; } public Audience? Audience { get; set; }
public int ExpiresInMinutes { get; set; } public int ExpiresInMinutes { get; set; }
public int RefreshTokenExpiresInDays { get; set; } public int RefreshTokenExpiresInDays { get; set; }
} }
public class Audience
{
public string? WebApp { get; set; }
public string? MobileApp { get; set; }
}
} }

View File

@ -160,7 +160,11 @@ if (jwtSettings != null && jwtSettings.Key != null)
ValidateLifetime = true, ValidateLifetime = true,
ValidateIssuerSigningKey = true, ValidateIssuerSigningKey = true,
ValidIssuer = jwtSettings.Issuer, ValidIssuer = jwtSettings.Issuer,
ValidAudience = jwtSettings.Audience, ValidAudiences = new List<string>
{
jwtSettings.Audience?.WebApp ?? "",
jwtSettings.Audience?.MobileApp ?? ""
},
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.Key)) IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.Key))
}; };

View File

@ -15,18 +15,25 @@ namespace MarcoBMS.Services.Service
private readonly ApplicationDbContext _context; private readonly ApplicationDbContext _context;
private readonly IMemoryCache _cache; // For optional JWT blacklisting private readonly IMemoryCache _cache; // For optional JWT blacklisting
private readonly ILoggingService _logger; private readonly ILoggingService _logger;
private string Origin;
public RefreshTokenService(ApplicationDbContext context, IMemoryCache cache, ILoggingService logger) public RefreshTokenService(ApplicationDbContext context, IMemoryCache cache, ILoggingService logger, IHttpContextAccessor httpContextAccessor)
{ {
_context = context; _context = context;
_cache = cache; _cache = cache;
_logger = logger; _logger = logger;
Origin = httpContextAccessor.HttpContext.Request.Headers["Origin"].FirstOrDefault() ?? "";
} }
public string GenerateJwtToken(string username, Guid tenantId, JwtSettings _jwtSettings) public string GenerateJwtToken(string username, Guid tenantId, JwtSettings _jwtSettings)
{ {
var audience = _jwtSettings.Audience.WebApp;
if (string.IsNullOrWhiteSpace(Origin))
{
audience = _jwtSettings.Audience.MobileApp;
_logger.LogError($"{audience}");
}
// Custom claims // Custom claims
var claims = new List<Claim> var claims = new List<Claim>
{ {
@ -40,7 +47,7 @@ namespace MarcoBMS.Services.Service
var token = new JwtSecurityToken( var token = new JwtSecurityToken(
issuer: _jwtSettings.Issuer, issuer: _jwtSettings.Issuer,
audience: _jwtSettings.Audience, audience: audience,
claims: claims, claims: claims,
expires: DateTime.UtcNow.AddMinutes(_jwtSettings.ExpiresInMinutes), expires: DateTime.UtcNow.AddMinutes(_jwtSettings.ExpiresInMinutes),
signingCredentials: creds); signingCredentials: creds);
@ -52,6 +59,12 @@ namespace MarcoBMS.Services.Service
{ {
try try
{ {
var audience = jwtSettings.Audience.WebApp;
if (string.IsNullOrWhiteSpace(Origin))
{
audience = jwtSettings.Audience.MobileApp;
_logger.LogError($"{audience}");
}
var claims = new[] var claims = new[]
{ {
new Claim(ClaimTypes.NameIdentifier, userId), new Claim(ClaimTypes.NameIdentifier, userId),
@ -67,7 +80,7 @@ namespace MarcoBMS.Services.Service
Subject = new ClaimsIdentity(claims), Subject = new ClaimsIdentity(claims),
Expires = DateTime.UtcNow.AddDays(jwtSettings.RefreshTokenExpiresInDays), Expires = DateTime.UtcNow.AddDays(jwtSettings.RefreshTokenExpiresInDays),
Issuer = jwtSettings.Issuer, Issuer = jwtSettings.Issuer,
Audience = jwtSettings.Audience, Audience = audience,
SigningCredentials = credentials SigningCredentials = credentials
}; };
@ -102,7 +115,6 @@ namespace MarcoBMS.Services.Service
{ {
try try
{ {
var claims = new[] var claims = new[]
{ {
new Claim(ClaimTypes.NameIdentifier, userId), new Claim(ClaimTypes.NameIdentifier, userId),
@ -117,7 +129,7 @@ namespace MarcoBMS.Services.Service
{ {
Subject = new ClaimsIdentity(claims), Subject = new ClaimsIdentity(claims),
Issuer = jwtSettings.Issuer, Issuer = jwtSettings.Issuer,
Audience = jwtSettings.Audience, Audience = jwtSettings.Audience.MobileApp,
SigningCredentials = creds SigningCredentials = creds
// No 'Expires' means the token won't expire // No 'Expires' means the token won't expire
}; };
@ -195,6 +207,12 @@ namespace MarcoBMS.Services.Service
public ClaimsPrincipal ValidateToken(string token, JwtSettings jwtSettings) public ClaimsPrincipal ValidateToken(string token, JwtSettings jwtSettings)
{ {
var audience = jwtSettings.Audience.WebApp;
if (string.IsNullOrWhiteSpace(Origin))
{
audience = jwtSettings.Audience.MobileApp;
_logger.LogError($"{audience}");
}
var tokenHandler = new JwtSecurityTokenHandler(); var tokenHandler = new JwtSecurityTokenHandler();
var key = System.Text.Encoding.ASCII.GetBytes(jwtSettings.Key); var key = System.Text.Encoding.ASCII.GetBytes(jwtSettings.Key);
@ -205,7 +223,7 @@ namespace MarcoBMS.Services.Service
ValidateIssuer = true, ValidateIssuer = true,
ValidIssuer = jwtSettings.Issuer, ValidIssuer = jwtSettings.Issuer,
ValidateAudience = true, ValidateAudience = true,
ValidAudience = jwtSettings.Audience, ValidAudience = audience,
ValidateLifetime = false, // Disable lifetime validation (ignores expiration) ValidateLifetime = false, // Disable lifetime validation (ignores expiration)
ClockSkew = TimeSpan.Zero // Optional: Remove time skew buffer ClockSkew = TimeSpan.Zero // Optional: Remove time skew buffer
}; };
@ -218,7 +236,7 @@ namespace MarcoBMS.Services.Service
catch (Exception ex) catch (Exception ex)
{ {
// Token is invalid // Token is invalid
Console.WriteLine($"Token validation failed: {ex.Message}"); _logger.LogError($"Token validation failed: {ex.Message}");
return null; return null;
} }
} }

View File

@ -31,7 +31,10 @@
}, },
"Jwt": { "Jwt": {
"Issuer": "http://localhost:5246", "Issuer": "http://localhost:5246",
"Audience": "http://localhost:5246", "Audience": {
"WebApp": "http://localhost:5246",
"MobileApp": "com.example.marcostage" // Use your actual application ID
},
"Key": "sworffishhkjfa9dnfdndfu33infnajfj", "Key": "sworffishhkjfa9dnfdndfu33infnajfj",
"ExpiresInMinutes": 60, "ExpiresInMinutes": 60,
"RefreshTokenExpiresInDays": 7 "RefreshTokenExpiresInDays": 7

View File

@ -6,7 +6,7 @@
}, },
"Environment": { "Environment": {
"Name": "Production", "Name": "Production",
"Title": "" "Title": ""
}, },
"ConnectionStrings": { "ConnectionStrings": {
"DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMS1" "DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMS1"
@ -23,8 +23,11 @@
"ImagesBaseUrl": "https://app.marcoaiot.com" "ImagesBaseUrl": "https://app.marcoaiot.com"
}, },
"Jwt": { "Jwt": {
"Issuer": "https://app.marcoaiot.com", "Issuer": "http://localhost:5246",
"Audience": "https://app.marcoaiot.com", "Audience": {
"WebApp": "http://localhost:5246",
"MobileApp": "com.example.marcostage" // Use your actual application ID
},
"Key": "sworffishhkjfa9dnfdndfu33infnajfj", "Key": "sworffishhkjfa9dnfdndfu33infnajfj",
"ExpiresInMinutes": 60, "ExpiresInMinutes": 60,
"RefreshTokenExpiresInDays": 7 "RefreshTokenExpiresInDays": 7