Files
tiku-backend.net/Tiku.IntegrationTests/Api/SecurityFoundationTests.cs
2026-07-26 12:51:56 +08:00

91 lines
3.0 KiB
C#

using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.IdentityModel.Tokens;
using Tiku.Application.Security;
using Tiku.Domain.Tenancy;
namespace Tiku.IntegrationTests.Api;
public sealed class SecurityFoundationTests
{
private static readonly JwtOptions JwtOptions = new()
{
Issuer = "tiku-backend",
Audience = "tiku-api",
SigningKey = "development-only-tiku-signing-key-change-before-production"
};
[Fact]
public async Task Authenticated_policy_returns_unauthorized_without_token()
{
await using var factory = CreateFactory();
using var client = factory.CreateClient();
var response = await client.GetAsync("/api/_security/authenticated");
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
}
[Fact]
public async Task Tenant_admin_policy_returns_forbidden_for_non_admin_member()
{
await using var factory = CreateFactory();
using var client = factory.CreateClient();
client.DefaultRequestHeaders.Authorization = new(
"Bearer",
CreateToken([
new Claim(TikuClaimTypes.UserId, Guid.NewGuid().ToString()),
new Claim(TikuClaimTypes.TenantId, Guid.NewGuid().ToString()),
new Claim(TikuClaimTypes.TenantRole, TenantRole.Student.ToString())
]));
var response = await client.GetAsync("/api/_security/tenant-admin");
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
}
[Fact]
public async Task Controller_pipeline_loads_authenticated_current_user()
{
var userId = Guid.NewGuid();
await using var factory = CreateFactory();
using var client = factory.CreateClient();
client.DefaultRequestHeaders.Authorization = new(
"Bearer",
CreateToken([
new Claim(TikuClaimTypes.UserId, userId.ToString())
]));
var response = await client.GetAsync("/api/_security/authenticated");
var body = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Contains(userId.ToString(), body, StringComparison.OrdinalIgnoreCase);
Assert.Contains("true", body, StringComparison.OrdinalIgnoreCase);
}
private static WebApplicationFactory<Program> CreateFactory()
{
return new WebApplicationFactory<Program>();
}
private static string CreateToken(IEnumerable<Claim> claims)
{
var credentials = new SigningCredentials(
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtOptions.SigningKey)),
SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
JwtOptions.Issuer,
JwtOptions.Audience,
claims,
expires: DateTime.UtcNow.AddMinutes(5),
signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}