feat(security): remover claim permisos del JWT post-UDT-009 [UDT-009]
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.Json;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using SIGCM2.Application.Abstractions.Security;
|
||||
@@ -44,13 +43,17 @@ public sealed class JwtService : IJwtService
|
||||
return principal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UDT-009: Generates an access token with minimal claims.
|
||||
/// Claim 'permisos' has been removed — authorization handler resolves permissions
|
||||
/// from DB per-request using IUsuarioRepository + PermisoResolver.
|
||||
/// Token claims: sub, jti, name, rol (+ standard iat/exp/nbf).
|
||||
/// </summary>
|
||||
public string GenerateAccessToken(Usuario usuario)
|
||||
{
|
||||
var signingKey = new RsaSecurityKey(_rsa);
|
||||
var credentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha256);
|
||||
|
||||
var permisos = DeserializePermisos(usuario.PermisosJson);
|
||||
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(JwtRegisteredClaimNames.Sub, usuario.Id.ToString()),
|
||||
@@ -59,10 +62,6 @@ public sealed class JwtService : IJwtService
|
||||
new("rol", usuario.Rol),
|
||||
};
|
||||
|
||||
// Add each permission as a separate claim
|
||||
foreach (var permiso in permisos)
|
||||
claims.Add(new Claim("permisos", permiso));
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
var descriptor = new SecurityTokenDescriptor
|
||||
{
|
||||
@@ -78,16 +77,4 @@ public sealed class JwtService : IJwtService
|
||||
var token = handler.CreateToken(descriptor);
|
||||
return handler.WriteToken(token);
|
||||
}
|
||||
|
||||
private static string[] DeserializePermisos(string permisosJson)
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonSerializer.Deserialize<string[]>(permisosJson) ?? [];
|
||||
}
|
||||
catch
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,59 @@ public class JwtServiceTests : IDisposable
|
||||
Assert.Contains("sigcm2.web", parsed.Audiences); // aud
|
||||
Assert.Contains(parsed.Claims, c => c.Type == "name" && c.Value == "admin");
|
||||
Assert.Contains(parsed.Claims, c => c.Type == "rol" && c.Value == "admin");
|
||||
|
||||
// J-01 (UDT-009): token must NOT contain 'permisos' claim post-UDT-009
|
||||
Assert.DoesNotContain(parsed.Claims, c => c.Type == "permisos");
|
||||
}
|
||||
|
||||
// J-01: token post-UDT-009 does NOT have 'permisos' claim
|
||||
[Fact]
|
||||
public void GenerateAccessToken_DoesNotContainPermisosClaim()
|
||||
{
|
||||
var usuario = MakeUsuario();
|
||||
var token = _jwtService.GenerateAccessToken(usuario);
|
||||
|
||||
var handler = new JwtSecurityTokenHandler();
|
||||
var parsed = handler.ReadJwtToken(token);
|
||||
|
||||
Assert.DoesNotContain(parsed.Claims, c => c.Type == "permisos");
|
||||
}
|
||||
|
||||
// J-02: claims present are sub, jti, name, rol (+ iat/exp/nbf) — no extras
|
||||
[Fact]
|
||||
public void GenerateAccessToken_HasExactlyExpectedClaims_NoPermisos()
|
||||
{
|
||||
var usuario = MakeUsuario();
|
||||
var token = _jwtService.GenerateAccessToken(usuario);
|
||||
|
||||
var handler = new JwtSecurityTokenHandler();
|
||||
var parsed = handler.ReadJwtToken(token);
|
||||
|
||||
// Must have sub, name, rol, jti
|
||||
Assert.Contains(parsed.Claims, c => c.Type == "sub");
|
||||
Assert.Contains(parsed.Claims, c => c.Type == "name");
|
||||
Assert.Contains(parsed.Claims, c => c.Type == "rol");
|
||||
Assert.Contains(parsed.Claims, c => c.Type == "jti");
|
||||
|
||||
// Must NOT have permisos
|
||||
Assert.DoesNotContain(parsed.Claims, c => c.Type == "permisos");
|
||||
}
|
||||
|
||||
// J-03: MakeUsuario with '["*"]' PermisosJson → token still has no 'permisos' claim
|
||||
[Fact]
|
||||
public void GenerateAccessToken_WithLegacyPermisosJson_NoPermisosClaim()
|
||||
{
|
||||
// MakeUsuario already uses '[\"*\"]' — this explicitly tests J-03
|
||||
var usuario = MakeUsuario();
|
||||
Assert.Equal("[\"*\"]", usuario.PermisosJson); // verify the helper
|
||||
|
||||
var token = _jwtService.GenerateAccessToken(usuario);
|
||||
|
||||
var handler = new JwtSecurityTokenHandler();
|
||||
var parsed = handler.ReadJwtToken(token);
|
||||
|
||||
// Post-UDT-009: JwtService ignores PermisosJson entirely — no claim emitted
|
||||
Assert.DoesNotContain(parsed.Claims, c => c.Type == "permisos");
|
||||
}
|
||||
|
||||
// Scenario: token is verifiable with the public key
|
||||
|
||||
Reference in New Issue
Block a user