diff --git a/src/Orbit.Api/Authorization/AdminAuthorizationHandler.cs b/src/Orbit.Api/Authorization/AdminAuthorizationHandler.cs
new file mode 100644
index 00000000..8d4ef2eb
--- /dev/null
+++ b/src/Orbit.Api/Authorization/AdminAuthorizationHandler.cs
@@ -0,0 +1,30 @@
+using System.Security.Claims;
+using Microsoft.AspNetCore.Authorization;
+using Orbit.Domain.Entities;
+using Orbit.Domain.Interfaces;
+
+namespace Orbit.Api.Authorization;
+
+///
+/// Marker requirement for the admin authorization boundary; satisfied by .
+///
+public sealed class AdminRequirement : IAuthorizationRequirement;
+
+///
+/// Authorizes admin-only endpoints by reading User.IsAdmin live from the database on every request,
+/// so revoking admin in the DB takes effect immediately rather than lingering until the caller's token expires.
+/// The JWT carries identity only; it never asserts admin.
+///
+public sealed class AdminAuthorizationHandler(IGenericRepository userRepository)
+ : AuthorizationHandler
+{
+ protected override async Task HandleRequirementAsync(
+ AuthorizationHandlerContext context, AdminRequirement requirement)
+ {
+ if (!Guid.TryParse(context.User.FindFirstValue(ClaimTypes.NameIdentifier), out var userId))
+ return;
+
+ if (await userRepository.AnyAsync(user => user.Id == userId && user.IsAdmin))
+ context.Succeed(requirement);
+ }
+}
diff --git a/src/Orbit.Api/Extensions/ServiceCollectionExtensions.cs b/src/Orbit.Api/Extensions/ServiceCollectionExtensions.cs
index 9f2e9d9c..131e6471 100644
--- a/src/Orbit.Api/Extensions/ServiceCollectionExtensions.cs
+++ b/src/Orbit.Api/Extensions/ServiceCollectionExtensions.cs
@@ -2,11 +2,13 @@
using FluentValidation;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Sentry;
using Sentry.AspNetCore;
using Orbit.Api.Authentication;
+using Orbit.Api.Authorization;
using Orbit.Api.OAuth;
using Orbit.Application.Behaviors;
using Orbit.Application.Common;
@@ -157,8 +159,9 @@ public static WebApplicationBuilder AddOrbitAuthentication(this WebApplicationBu
builder.Services.AddAuthorization(options =>
{
options.AddPolicy(AdminPolicy.Name, policy =>
- policy.RequireClaim(AdminPolicy.ClaimType, AdminPolicy.ClaimValue));
+ policy.Requirements.Add(new AdminRequirement()));
});
+ builder.Services.AddScoped();
return builder;
}
diff --git a/src/Orbit.Application/Auth/Commands/GoogleAuthCommand.cs b/src/Orbit.Application/Auth/Commands/GoogleAuthCommand.cs
index 3e6cc244..50ff9786 100644
--- a/src/Orbit.Application/Auth/Commands/GoogleAuthCommand.cs
+++ b/src/Orbit.Application/Auth/Commands/GoogleAuthCommand.cs
@@ -44,7 +44,7 @@ public async Task> Handle(GoogleAuthCommand request, Cance
if (wasReactivated || request.GoogleAccessToken is not null)
await unitOfWork.SaveChangesAsync(cancellationToken);
- var sessionResult = await authSessionService.CreateSessionAsync(user.Id, user.Email, user.IsAdmin, cancellationToken);
+ var sessionResult = await authSessionService.CreateSessionAsync(user.Id, user.Email, cancellationToken);
if (sessionResult.IsFailure)
return sessionResult.PropagateError();
diff --git a/src/Orbit.Application/Auth/Commands/VerifyCodeCommand.cs b/src/Orbit.Application/Auth/Commands/VerifyCodeCommand.cs
index e7b40cc9..58eefbd5 100644
--- a/src/Orbit.Application/Auth/Commands/VerifyCodeCommand.cs
+++ b/src/Orbit.Application/Auth/Commands/VerifyCodeCommand.cs
@@ -40,7 +40,7 @@ public async Task> Handle(VerifyCodeCommand request, Cance
var wasReactivated = await HandlePostLoginAsync(user, isNewUser, request, cancellationToken);
- var sessionResult = await authSessionService.CreateSessionAsync(user.Id, user.Email, user.IsAdmin, cancellationToken);
+ var sessionResult = await authSessionService.CreateSessionAsync(user.Id, user.Email, cancellationToken);
if (sessionResult.IsFailure)
return sessionResult.PropagateError();
diff --git a/src/Orbit.Application/Common/AdminPolicy.cs b/src/Orbit.Application/Common/AdminPolicy.cs
index 6b3dbd8a..94ed6917 100644
--- a/src/Orbit.Application/Common/AdminPolicy.cs
+++ b/src/Orbit.Application/Common/AdminPolicy.cs
@@ -1,14 +1,12 @@
namespace Orbit.Application.Common;
///
-/// Names the single administrative authorization boundary. A user's IsAdmin flag mints the
-/// admin claim into the JWT; the "Admin" policy (RequireClaim on that claim) gates admin-only
-/// endpoints. The first admin is granted by a direct DB update (Users.IsAdmin = true); there is
-/// no email-based gate.
+/// Names the single administrative authorization boundary. The "Admin" policy reads
+/// User.IsAdmin live from the database on every request, so revoking admin takes effect
+/// immediately; the JWT carries identity only and never asserts admin. The first admin is granted
+/// by a direct DB update (Users.IsAdmin = true).
///
public static class AdminPolicy
{
public const string Name = "Admin";
- public const string ClaimType = "admin";
- public const string ClaimValue = "true";
}
diff --git a/src/Orbit.Domain/Interfaces/IAuthSessionService.cs b/src/Orbit.Domain/Interfaces/IAuthSessionService.cs
index 4fa123d2..8f923ab4 100644
--- a/src/Orbit.Domain/Interfaces/IAuthSessionService.cs
+++ b/src/Orbit.Domain/Interfaces/IAuthSessionService.cs
@@ -5,7 +5,7 @@ namespace Orbit.Domain.Interfaces;
public interface IAuthSessionService
{
- Task> CreateSessionAsync(Guid userId, string email, bool isAdmin, CancellationToken cancellationToken = default);
+ Task> CreateSessionAsync(Guid userId, string email, CancellationToken cancellationToken = default);
Task> RefreshSessionAsync(string refreshToken, CancellationToken cancellationToken = default);
Task RevokeSessionAsync(string refreshToken, CancellationToken cancellationToken = default);
}
diff --git a/src/Orbit.Domain/Interfaces/ITokenService.cs b/src/Orbit.Domain/Interfaces/ITokenService.cs
index 257475a0..298512d9 100644
--- a/src/Orbit.Domain/Interfaces/ITokenService.cs
+++ b/src/Orbit.Domain/Interfaces/ITokenService.cs
@@ -2,5 +2,5 @@ namespace Orbit.Domain.Interfaces;
public interface ITokenService
{
- string GenerateToken(Guid userId, string email, bool isAdmin);
+ string GenerateToken(Guid userId, string email);
}
diff --git a/src/Orbit.Infrastructure/Services/AuthSessionService.cs b/src/Orbit.Infrastructure/Services/AuthSessionService.cs
index 7c91b05c..88f194a1 100644
--- a/src/Orbit.Infrastructure/Services/AuthSessionService.cs
+++ b/src/Orbit.Infrastructure/Services/AuthSessionService.cs
@@ -24,7 +24,7 @@ public class AuthSessionService(
? nowUtc.AddDays(_jwtSettings.RefreshExpiryDays.Value)
: null;
- public async Task> CreateSessionAsync(Guid userId, string email, bool isAdmin, CancellationToken cancellationToken = default)
+ public async Task> CreateSessionAsync(Guid userId, string email, CancellationToken cancellationToken = default)
{
var refreshToken = GenerateRefreshToken();
var nowUtc = DateTime.UtcNow;
@@ -40,7 +40,7 @@ public async Task> CreateSessionAsync(Guid userId, string
await unitOfWork.SaveChangesAsync(cancellationToken);
return Result.Success(new SessionTokens(
- tokenService.GenerateToken(userId, email, isAdmin),
+ tokenService.GenerateToken(userId, email),
refreshToken));
}
@@ -69,7 +69,7 @@ public async Task> RefreshSessionAsync(string refreshToken
await unitOfWork.SaveChangesAsync(cancellationToken);
return Result.Success(new SessionTokens(
- tokenService.GenerateToken(user.Id, user.Email, user.IsAdmin),
+ tokenService.GenerateToken(user.Id, user.Email),
newRefreshToken));
}
diff --git a/src/Orbit.Infrastructure/Services/JwtTokenService.cs b/src/Orbit.Infrastructure/Services/JwtTokenService.cs
index ce0d6d1e..028b0ece 100644
--- a/src/Orbit.Infrastructure/Services/JwtTokenService.cs
+++ b/src/Orbit.Infrastructure/Services/JwtTokenService.cs
@@ -13,7 +13,7 @@ public class JwtTokenService(IOptions options) : ITokenService
{
private readonly JwtSettings _settings = options.Value;
- public string GenerateToken(Guid userId, string email, bool isAdmin)
+ public string GenerateToken(Guid userId, string email)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_settings.SecretKey));
@@ -24,9 +24,6 @@ public string GenerateToken(Guid userId, string email, bool isAdmin)
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
- if (isAdmin)
- claims.Add(new Claim(AdminPolicy.ClaimType, AdminPolicy.ClaimValue));
-
var descriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
diff --git a/src/Orbit.Infrastructure/Services/ResendEmailService.cs b/src/Orbit.Infrastructure/Services/ResendEmailService.cs
index 736477b4..00ef61eb 100644
--- a/src/Orbit.Infrastructure/Services/ResendEmailService.cs
+++ b/src/Orbit.Infrastructure/Services/ResendEmailService.cs
@@ -110,7 +110,10 @@ public async Task SendMarketingEmailAsync(
var isPtBr = LocaleHelper.IsPortuguese(language);
var footer = MarketingFooterHtml(isPtBr, unsubscribeUrl);
var layout = new EmailLayout(LangCode(isPtBr), Preheader: "", footer, LogoUrl, GradientHeader: true);
- var html = EmailTemplateRenderer.RenderLayout(layout, bodyHtml);
+ var readableBody =
+ "{bodyHtml}
";
+ var html = EmailTemplateRenderer.RenderLayout(layout, readableBody);
var payload = new
{
@@ -131,7 +134,7 @@ public async Task SendMarketingEmailAsync(
private static string MarketingFooterHtml(bool isPtBr, string unsubscribeUrl)
{
const string legalIdentity =
- "TL SOFTWARE ENGINEERING LTDA · CNPJ 58.429.979/0001-06 · Av. Nova Independência, 651 — Brooklin Paulista, São Paulo – SP · CEP 04570-001";
+ "TL SOFTWARE ENGINEERING LTDA · CNPJ 58.429.979/0001-06 · Av. Nova Independência, 651, Brooklin Paulista, São Paulo/SP · CEP 04570-001";
var (reason, unsubscribeLabel) = isPtBr
? ("Você está recebendo este e-mail porque optou por receber novidades do Orbit.", "Cancelar inscrição")
diff --git a/tests/Orbit.Application.Tests/Commands/Auth/AuthCommandHandlerTests.cs b/tests/Orbit.Application.Tests/Commands/Auth/AuthCommandHandlerTests.cs
index 6ce3c472..cc92b961 100644
--- a/tests/Orbit.Application.Tests/Commands/Auth/AuthCommandHandlerTests.cs
+++ b/tests/Orbit.Application.Tests/Commands/Auth/AuthCommandHandlerTests.cs
@@ -61,7 +61,7 @@ public async Task VerifyCode_Valid_ReturnsLoginResponse()
var user = User.Create("Test", TestEmail).Value;
SetupCacheWithCode("123456");
SetupExistingUser(user);
- _authSessionService.CreateSessionAsync(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any())
+ _authSessionService.CreateSessionAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns(Result.Success(new SessionTokens("jwt-token", "refresh-token")));
var handler = new VerifyCodeCommandHandler(_cache, _userRepo, _unitOfWork, _authSessionService, _emailService, Substitute.For(), Substitute.For>());
@@ -111,7 +111,7 @@ public async Task VerifyCode_MaxAttempts_ReturnsFailure()
public async Task VerifyCode_NewUser_CreatesAccount()
{
SetupCacheWithCode("123456");
- _authSessionService.CreateSessionAsync(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any())
+ _authSessionService.CreateSessionAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns(Result.Success(new SessionTokens("jwt-token", "refresh-token")));
var handler = new VerifyCodeCommandHandler(_cache, _userRepo, _unitOfWork, _authSessionService, _emailService, Substitute.For(), Substitute.For>());
@@ -130,7 +130,7 @@ public async Task VerifyCode_ExistingUser_ReturnsToken()
var user = User.Create("Existing", TestEmail).Value;
SetupCacheWithCode("123456");
SetupExistingUser(user);
- _authSessionService.CreateSessionAsync(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any())
+ _authSessionService.CreateSessionAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns(Result.Success(new SessionTokens("jwt-token", "refresh-token")));
var handler = new VerifyCodeCommandHandler(_cache, _userRepo, _unitOfWork, _authSessionService, _emailService, Substitute.For(), Substitute.For>());
diff --git a/tests/Orbit.Application.Tests/Commands/Auth/GoogleAuthCommandHandlerTests.cs b/tests/Orbit.Application.Tests/Commands/Auth/GoogleAuthCommandHandlerTests.cs
index de60ecf4..4e5364fb 100644
--- a/tests/Orbit.Application.Tests/Commands/Auth/GoogleAuthCommandHandlerTests.cs
+++ b/tests/Orbit.Application.Tests/Commands/Auth/GoogleAuthCommandHandlerTests.cs
@@ -41,7 +41,7 @@ public GoogleAuthCommandHandlerTests()
Substitute.For(),
Substitute.For>());
- _authSessionService.CreateSessionAsync(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any())
+ _authSessionService.CreateSessionAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns(Result.Success(new SessionTokens("jwt-token", "refresh-token")));
}
diff --git a/tests/Orbit.Application.Tests/Commands/Auth/SendCodeCommandHandlerTests.cs b/tests/Orbit.Application.Tests/Commands/Auth/SendCodeCommandHandlerTests.cs
index 8ea0a121..6edc9cfe 100644
--- a/tests/Orbit.Application.Tests/Commands/Auth/SendCodeCommandHandlerTests.cs
+++ b/tests/Orbit.Application.Tests/Commands/Auth/SendCodeCommandHandlerTests.cs
@@ -153,7 +153,7 @@ private VerifyCodeCommandHandler BuildVerifyHandler()
var authSessionService = Substitute.For();
var mediator = Substitute.For();
- authSessionService.CreateSessionAsync(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any())
+ authSessionService.CreateSessionAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns(Result.Success(new SessionTokens("jwt-token", "refresh-token")));
return new VerifyCodeCommandHandler(
diff --git a/tests/Orbit.Application.Tests/Commands/Auth/VerifyCodeCommandHandlerTests.cs b/tests/Orbit.Application.Tests/Commands/Auth/VerifyCodeCommandHandlerTests.cs
index f44c7faf..0726843e 100644
--- a/tests/Orbit.Application.Tests/Commands/Auth/VerifyCodeCommandHandlerTests.cs
+++ b/tests/Orbit.Application.Tests/Commands/Auth/VerifyCodeCommandHandlerTests.cs
@@ -33,7 +33,7 @@ public VerifyCodeCommandHandlerTests()
_cache, _userRepo, _unitOfWork, _authSessionService, _emailService, _mediator,
Substitute.For>());
- _authSessionService.CreateSessionAsync(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any())
+ _authSessionService.CreateSessionAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns(Result.Success(new SessionTokens("jwt-token", "refresh-token")));
}
diff --git a/tests/Orbit.Application.Tests/Services/AuthSessionServiceTests.cs b/tests/Orbit.Application.Tests/Services/AuthSessionServiceTests.cs
index 41e1568d..f37fe7de 100644
--- a/tests/Orbit.Application.Tests/Services/AuthSessionServiceTests.cs
+++ b/tests/Orbit.Application.Tests/Services/AuthSessionServiceTests.cs
@@ -66,14 +66,14 @@ public AuthSessionServiceTests()
.Returns(_user);
_tokenService
- .GenerateToken(Arg.Any(), Arg.Any(), Arg.Any())
+ .GenerateToken(Arg.Any(), Arg.Any())
.Returns("access-token-1", "access-token-2", "access-token-3");
}
[Fact]
public async Task CreateSessionAsync_WithNullRefreshExpiry_CreatesNonExpiringSession()
{
- var result = await _service.CreateSessionAsync(_user.Id, _user.Email, false, CancellationToken.None);
+ var result = await _service.CreateSessionAsync(_user.Id, _user.Email, CancellationToken.None);
result.IsSuccess.Should().BeTrue();
result.Value.AccessToken.Should().Be("access-token-1");
@@ -86,7 +86,7 @@ public async Task CreateSessionAsync_WithNullRefreshExpiry_CreatesNonExpiringSes
[Fact]
public async Task RefreshSessionAsync_WithNonExpiringSession_RotatesRefreshTokenWithoutAddingExpiry()
{
- var createResult = await _service.CreateSessionAsync(_user.Id, _user.Email, false, CancellationToken.None);
+ var createResult = await _service.CreateSessionAsync(_user.Id, _user.Email, CancellationToken.None);
var originalTokenHash = _storedSession!.TokenHash;
var originalLastUsedAtUtc = _storedSession.LastUsedAtUtc;
@@ -106,7 +106,7 @@ public async Task RefreshSessionAsync_WithNonExpiringSession_RotatesRefreshToken
[Fact]
public async Task RevokeSessionAsync_RevokesStoredSession()
{
- var createResult = await _service.CreateSessionAsync(_user.Id, _user.Email, false, CancellationToken.None);
+ var createResult = await _service.CreateSessionAsync(_user.Id, _user.Email, CancellationToken.None);
var revokeResult = await _service.RevokeSessionAsync(createResult.Value.RefreshToken, CancellationToken.None);
@@ -117,7 +117,7 @@ public async Task RevokeSessionAsync_RevokesStoredSession()
[Fact]
public async Task RefreshSessionAsync_WithRevokedSession_ReturnsFailure()
{
- var createResult = await _service.CreateSessionAsync(_user.Id, _user.Email, false, CancellationToken.None);
+ var createResult = await _service.CreateSessionAsync(_user.Id, _user.Email, CancellationToken.None);
_storedSession!.Revoke(DateTime.UtcNow);
var refreshResult = await _service.RefreshSessionAsync(createResult.Value.RefreshToken, CancellationToken.None);
diff --git a/tests/Orbit.Infrastructure.Tests/Authorization/AdminAuthorizationPolicyTests.cs b/tests/Orbit.Infrastructure.Tests/Authorization/AdminAuthorizationPolicyTests.cs
index 1a48c1fd..8d00dc31 100644
--- a/tests/Orbit.Infrastructure.Tests/Authorization/AdminAuthorizationPolicyTests.cs
+++ b/tests/Orbit.Infrastructure.Tests/Authorization/AdminAuthorizationPolicyTests.cs
@@ -1,46 +1,75 @@
+using System.Linq.Expressions;
using System.Security.Claims;
using FluentAssertions;
using Microsoft.AspNetCore.Authorization;
-using Microsoft.Extensions.DependencyInjection;
-using Orbit.Application.Common;
+using NSubstitute;
+using Orbit.Api.Authorization;
+using Orbit.Domain.Entities;
+using Orbit.Domain.Interfaces;
namespace Orbit.Infrastructure.Tests.Authorization;
public class AdminAuthorizationPolicyTests
{
- private static IAuthorizationService BuildAuthorizationService()
+ private readonly IGenericRepository _userRepository = Substitute.For>();
+ private readonly AdminAuthorizationHandler _handler;
+
+ public AdminAuthorizationPolicyTests()
+ {
+ _handler = new AdminAuthorizationHandler(_userRepository);
+ }
+
+ [Fact]
+ public async Task AdminUser_Succeeds()
{
- var services = new ServiceCollection();
- services.AddLogging();
- services.AddAuthorization(options =>
- options.AddPolicy(AdminPolicy.Name, policy =>
- policy.RequireClaim(AdminPolicy.ClaimType, AdminPolicy.ClaimValue)));
+ _userRepository.AnyAsync(Arg.Any>>(), Arg.Any())
+ .Returns(true);
+ var context = ContextFor(Principal(new Claim(ClaimTypes.NameIdentifier, Guid.NewGuid().ToString())));
- return services.BuildServiceProvider().GetRequiredService();
+ await _handler.HandleAsync(context);
+
+ context.HasSucceeded.Should().BeTrue();
}
- private static ClaimsPrincipal Principal(params Claim[] claims) =>
- new(new ClaimsIdentity(claims, authenticationType: "Test"));
+ [Fact]
+ public async Task AuthenticatedNonAdmin_DoesNotSucceed()
+ {
+ _userRepository.AnyAsync(Arg.Any>>(), Arg.Any())
+ .Returns(false);
+ var context = ContextFor(Principal(new Claim(ClaimTypes.NameIdentifier, Guid.NewGuid().ToString())));
+
+ await _handler.HandleAsync(context);
+
+ context.HasSucceeded.Should().BeFalse();
+ }
[Fact]
- public async Task AdminClaim_IsAllowed()
+ public async Task MissingNameIdentifier_DoesNotSucceed_AndSkipsRepository()
{
- var principal = Principal(
- new Claim(ClaimTypes.NameIdentifier, Guid.NewGuid().ToString()),
- new Claim(AdminPolicy.ClaimType, AdminPolicy.ClaimValue));
+ var context = ContextFor(Principal());
- var result = await BuildAuthorizationService().AuthorizeAsync(principal, resource: null, AdminPolicy.Name);
+ await _handler.HandleAsync(context);
- result.Succeeded.Should().BeTrue();
+ context.HasSucceeded.Should().BeFalse();
+ await _userRepository.DidNotReceive()
+ .AnyAsync(Arg.Any>>(), Arg.Any());
}
[Fact]
- public async Task AuthenticatedNonAdmin_IsDenied()
+ public async Task UnparseableNameIdentifier_DoesNotSucceed_AndSkipsRepository()
{
- var principal = Principal(new Claim(ClaimTypes.NameIdentifier, Guid.NewGuid().ToString()));
+ var context = ContextFor(Principal(new Claim(ClaimTypes.NameIdentifier, "not-a-guid")));
- var result = await BuildAuthorizationService().AuthorizeAsync(principal, resource: null, AdminPolicy.Name);
+ await _handler.HandleAsync(context);
- result.Succeeded.Should().BeFalse();
+ context.HasSucceeded.Should().BeFalse();
+ await _userRepository.DidNotReceive()
+ .AnyAsync(Arg.Any>>(), Arg.Any());
}
+
+ private static ClaimsPrincipal Principal(params Claim[] claims) =>
+ new(new ClaimsIdentity(claims, authenticationType: "Test"));
+
+ private static AuthorizationHandlerContext ContextFor(ClaimsPrincipal principal) =>
+ new([new AdminRequirement()], principal, resource: null);
}
diff --git a/tests/Orbit.Infrastructure.Tests/Services/AuthSessionServiceTests.cs b/tests/Orbit.Infrastructure.Tests/Services/AuthSessionServiceTests.cs
index 1a89e2d5..c85c060c 100644
--- a/tests/Orbit.Infrastructure.Tests/Services/AuthSessionServiceTests.cs
+++ b/tests/Orbit.Infrastructure.Tests/Services/AuthSessionServiceTests.cs
@@ -20,7 +20,7 @@ public class AuthSessionServiceTests
public AuthSessionServiceTests()
{
- _tokenService.GenerateToken(Arg.Any(), Arg.Any(), Arg.Any()).Returns("access-token");
+ _tokenService.GenerateToken(Arg.Any(), Arg.Any()).Returns("access-token");
_sut = new AuthSessionService(
_userSessionRepository,
@@ -42,7 +42,7 @@ public async Task CreateSessionAsync_AddsPersistedSessionAndReturnsTokens()
{
var userId = Guid.NewGuid();
- var result = await _sut.CreateSessionAsync(userId, "thomas@test.com", false, CancellationToken.None);
+ var result = await _sut.CreateSessionAsync(userId, "thomas@test.com", CancellationToken.None);
result.IsSuccess.Should().BeTrue();
result.Value.AccessToken.Should().Be("access-token");
@@ -59,7 +59,7 @@ await _userSessionRepository.AddAsync(
Arg.Do(session => captured = session),
Arg.Any());
- await _sut.CreateSessionAsync(Guid.NewGuid(), "thomas@test.com", false, CancellationToken.None);
+ await _sut.CreateSessionAsync(Guid.NewGuid(), "thomas@test.com", CancellationToken.None);
captured.Should().NotBeNull();
captured!.ExpiresAtUtc.Should().NotBeNull();
diff --git a/tests/Orbit.Infrastructure.Tests/Services/JwtTokenServiceTests.cs b/tests/Orbit.Infrastructure.Tests/Services/JwtTokenServiceTests.cs
index 7507161c..3e6f4a8d 100644
--- a/tests/Orbit.Infrastructure.Tests/Services/JwtTokenServiceTests.cs
+++ b/tests/Orbit.Infrastructure.Tests/Services/JwtTokenServiceTests.cs
@@ -3,7 +3,6 @@
using FluentAssertions;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
-using Orbit.Application.Common;
using Orbit.Infrastructure.Configuration;
using Orbit.Infrastructure.Services;
@@ -34,7 +33,7 @@ public void GenerateToken_ReturnsNonEmptyString()
var userId = Guid.NewGuid();
var email = "test@example.com";
- var token = _sut.GenerateToken(userId, email, false);
+ var token = _sut.GenerateToken(userId, email);
token.Should().NotBeNullOrWhiteSpace();
}
@@ -45,7 +44,7 @@ public void GenerateToken_ContainsUserIdClaim()
var userId = Guid.NewGuid();
var email = "test@example.com";
- var token = _sut.GenerateToken(userId, email, false);
+ var token = _sut.GenerateToken(userId, email);
var handler = new JwtSecurityTokenHandler();
var jwt = handler.ReadJwtToken(token);
@@ -61,7 +60,7 @@ public void GenerateToken_ContainsEmailClaim()
var userId = Guid.NewGuid();
var email = "user@orbit.test";
- var token = _sut.GenerateToken(userId, email, false);
+ var token = _sut.GenerateToken(userId, email);
var handler = new JwtSecurityTokenHandler();
var jwt = handler.ReadJwtToken(token);
@@ -72,24 +71,15 @@ public void GenerateToken_ContainsEmailClaim()
}
[Fact]
- public void GenerateToken_WhenAdmin_ContainsAdminClaim()
+ public void GenerateToken_OmitsAdminClaim()
{
- var token = _sut.GenerateToken(Guid.NewGuid(), "admin@orbit.test", isAdmin: true);
+ var token = _sut.GenerateToken(Guid.NewGuid(), "user@orbit.test");
var jwt = new JwtSecurityTokenHandler().ReadJwtToken(token);
- jwt.Claims.Should().Contain(c =>
- c.Type == AdminPolicy.ClaimType && c.Value == AdminPolicy.ClaimValue);
- }
-
- [Fact]
- public void GenerateToken_WhenNotAdmin_OmitsAdminClaim()
- {
- var token = _sut.GenerateToken(Guid.NewGuid(), "user@orbit.test", isAdmin: false);
-
- var jwt = new JwtSecurityTokenHandler().ReadJwtToken(token);
-
- jwt.Claims.Should().NotContain(c => c.Type == AdminPolicy.ClaimType);
+ jwt.Claims.Should().NotContain(c =>
+ c.Type.Contains("admin", StringComparison.OrdinalIgnoreCase)
+ || c.Value.Contains("admin", StringComparison.OrdinalIgnoreCase));
}
[Fact]
@@ -99,7 +89,7 @@ public void GenerateToken_SetsCorrectExpiry()
var email = "test@example.com";
var beforeGeneration = DateTime.UtcNow;
- var token = _sut.GenerateToken(userId, email, false);
+ var token = _sut.GenerateToken(userId, email);
var handler = new JwtSecurityTokenHandler();
var jwt = handler.ReadJwtToken(token);