-
Notifications
You must be signed in to change notification settings - Fork 0
Test #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Test #10
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,283 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using FluentAssertions; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.AspNetCore.Http; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.AspNetCore.Mvc; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.AspNetCore.Mvc.Abstractions; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.AspNetCore.Mvc.Filters; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.AspNetCore.Routing; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.Extensions.DependencyInjection; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.Extensions.Logging; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Moq; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using ProjectVG.Api.Filters; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using ProjectVG.Common.Constants; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using ProjectVG.Common.Exceptions; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using ProjectVG.Infrastructure.Auth; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System.Security.Claims; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Xunit; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
namespace ProjectVG.Tests.Api.Filters | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public class JwtAuthenticationFilterTests | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly Mock<ITokenService> _mockTokenService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly Mock<ILogger<JwtAuthenticationAttribute>> _mockLogger; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly JwtAuthenticationAttribute _filter; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly ServiceProvider _serviceProvider; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public JwtAuthenticationFilterTests() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService = new Mock<ITokenService>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockLogger = new Mock<ILogger<JwtAuthenticationAttribute>>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var services = new ServiceCollection(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
services.AddSingleton(_mockTokenService.Object); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
services.AddSingleton(_mockLogger.Object); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_serviceProvider = services.BuildServiceProvider(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_filter = new JwtAuthenticationAttribute(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private AuthorizationFilterContext CreateFilterContext(string? headerName = null, string? headerValue = null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var httpContext = new DefaultHttpContext | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RequestServices = _serviceProvider | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!string.IsNullOrEmpty(headerName) && !string.IsNullOrEmpty(headerValue)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
httpContext.Request.Headers[headerName] = headerValue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var actionContext = new ActionContext( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
httpContext, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
new RouteData(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
new ActionDescriptor() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return new AuthorizationFilterContext(actionContext, new List<IFilterMetadata>()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#region Token Extraction Tests | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Theory] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[InlineData("Authorization", "Bearer valid-token-123")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[InlineData("X-Forwarded-Authorization", "Bearer forwarded-token-456")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[InlineData("X-Original-Authorization", "Bearer original-token-789")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[InlineData("HTTP_AUTHORIZATION", "Bearer http-token-abc")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task OnAuthorizationAsync_ValidTokenInDifferentHeaders_ShouldAuthenticate(string headerName, string headerValue) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Arrange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var userId = Guid.NewGuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var expectedToken = headerValue.Substring("Bearer ".Length); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var filterContext = CreateFilterContext(headerName, headerValue); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService.Setup(x => x.ValidateAccessTokenAsync(expectedToken)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.ReturnsAsync(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService.Setup(x => x.GetUserIdFromTokenAsync(expectedToken)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.ReturnsAsync(userId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Act | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await _filter.OnAuthorizationAsync(filterContext); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Assert | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
filterContext.HttpContext.User.Should().NotBeNull(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
filterContext.HttpContext.User.Identity!.IsAuthenticated.Should().BeTrue(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
filterContext.HttpContext.User.Identity.AuthenticationType.Should().Be("Bearer"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var userIdClaim = filterContext.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
userIdClaim.Should().NotBeNull(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
userIdClaim!.Value.Should().Be(userId.ToString()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var customUserIdClaim = filterContext.HttpContext.User.FindFirst("user_id"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
customUserIdClaim.Should().NotBeNull(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
customUserIdClaim!.Value.Should().Be(userId.ToString()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task OnAuthorizationAsync_TokenWithExtraSpaces_ShouldTrimAndUse() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Arrange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var userId = Guid.NewGuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var token = "token-with-spaces"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var filterContext = CreateFilterContext("Authorization", $"Bearer {token} "); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService.Setup(x => x.ValidateAccessTokenAsync(token)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.ReturnsAsync(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService.Setup(x => x.GetUserIdFromTokenAsync(token)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.ReturnsAsync(userId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Act | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await _filter.OnAuthorizationAsync(filterContext); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Assert | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService.Verify(x => x.ValidateAccessTokenAsync(token), Times.Once); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
filterContext.HttpContext.User.Identity!.IsAuthenticated.Should().BeTrue(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#endregion | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#region Token Missing Tests | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task OnAuthorizationAsync_NoAuthorizationHeader_ShouldThrowTokenMissingException() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Arrange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var filterContext = CreateFilterContext(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Act & Assert | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var exception = await Assert.ThrowsAsync<AuthenticationException>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
() => _filter.OnAuthorizationAsync(filterContext) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
exception.ErrorCode.Should().Be(ErrorCode.TOKEN_MISSING); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task OnAuthorizationAsync_EmptyAuthorizationHeader_ShouldThrowTokenMissingException() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Arrange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var filterContext = CreateFilterContext("Authorization", ""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Act & Assert | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var exception = await Assert.ThrowsAsync<AuthenticationException>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
() => _filter.OnAuthorizationAsync(filterContext) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
exception.ErrorCode.Should().Be(ErrorCode.TOKEN_MISSING); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+135
to
+147
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainEmptyAuthorizationHeader 테스트가 현재 ‘헤더 없음’과 동일하게 동작합니다 위 CreateFilterContext 수정 전까지는 이 테스트가 실제로 헤더를 추가하지 않습니다. 헬퍼를 수정하지 않는다면 아래처럼 테스트에서 직접 헤더를 설정해 주세요. 수정 후 두 테스트(헤더 없음/빈 헤더)가 확실히 분리되는지 확인 바랍니다. - var filterContext = CreateFilterContext("Authorization", "");
+ var filterContext = CreateFilterContext();
+ filterContext.HttpContext.Request.Headers["Authorization"] = string.Empty; 🏁 Script executed: #!/bin/bash
# 검색: CreateFilterContext 정의 및 사용 위치 확인
rg -nP '\bCreateFilterContext\b' -C3 --type=cs Length of output: 8500 🏁 Script executed: sed -n '30,80p' ProjectVG.Tests/Api/Filters/JwtAuthenticationFilterTests.cs Length of output: 2158 EmptyAuthorizationHeader 테스트에 빈 헤더가 실제로 설정되도록 수정 필요 - var filterContext = CreateFilterContext("Authorization", "");
+ var filterContext = CreateFilterContext();
+ filterContext.HttpContext.Request.Headers["Authorization"] = string.Empty; 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task OnAuthorizationAsync_BearerWithoutToken_ShouldThrowTokenMissingException() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Arrange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var filterContext = CreateFilterContext("Authorization", "Bearer"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Act & Assert | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var exception = await Assert.ThrowsAsync<AuthenticationException>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
() => _filter.OnAuthorizationAsync(filterContext) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
exception.ErrorCode.Should().Be(ErrorCode.TOKEN_MISSING); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task OnAuthorizationAsync_BearerWithEmptyToken_ShouldThrowTokenMissingException() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Arrange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var filterContext = CreateFilterContext("Authorization", "Bearer "); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Act & Assert | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var exception = await Assert.ThrowsAsync<AuthenticationException>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
() => _filter.OnAuthorizationAsync(filterContext) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
exception.ErrorCode.Should().Be(ErrorCode.TOKEN_MISSING); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#endregion | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#region Token Validation Tests | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task OnAuthorizationAsync_InvalidToken_ShouldThrowTokenInvalidException() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Arrange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var invalidToken = "invalid-token"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var filterContext = CreateFilterContext("Authorization", $"Bearer {invalidToken}"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService.Setup(x => x.ValidateAccessTokenAsync(invalidToken)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.ReturnsAsync(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Act & Assert | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var exception = await Assert.ThrowsAsync<AuthenticationException>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
() => _filter.OnAuthorizationAsync(filterContext) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
exception.ErrorCode.Should().Be(ErrorCode.TOKEN_INVALID); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#endregion | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#region User ID Extraction Tests | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task OnAuthorizationAsync_ValidTokenButNoUserId_ShouldThrowAuthenticationFailedException() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Arrange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var validToken = "valid-token-no-user"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var filterContext = CreateFilterContext("Authorization", $"Bearer {validToken}"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService.Setup(x => x.ValidateAccessTokenAsync(validToken)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.ReturnsAsync(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService.Setup(x => x.GetUserIdFromTokenAsync(validToken)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.ReturnsAsync((Guid?)null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Act & Assert | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var exception = await Assert.ThrowsAsync<AuthenticationException>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
() => _filter.OnAuthorizationAsync(filterContext) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
exception.ErrorCode.Should().Be(ErrorCode.AUTHENTICATION_FAILED); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#endregion | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#region Successful Authentication Tests | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task OnAuthorizationAsync_ValidTokenAndUserId_ShouldSetUserWithCorrectClaims() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Arrange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var userId = Guid.NewGuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var validToken = "valid-token-123"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var filterContext = CreateFilterContext("Authorization", $"Bearer {validToken}"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService.Setup(x => x.ValidateAccessTokenAsync(validToken)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.ReturnsAsync(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService.Setup(x => x.GetUserIdFromTokenAsync(validToken)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.ReturnsAsync(userId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Act | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await _filter.OnAuthorizationAsync(filterContext); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Assert | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var user = filterContext.HttpContext.User; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
user.Should().NotBeNull(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
user.Identity!.IsAuthenticated.Should().BeTrue(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
user.Identity.AuthenticationType.Should().Be("Bearer"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var nameIdentifierClaim = user.FindFirst(ClaimTypes.NameIdentifier); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
nameIdentifierClaim.Should().NotBeNull(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
nameIdentifierClaim!.Value.Should().Be(userId.ToString()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var userIdClaim = user.FindFirst("user_id"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
userIdClaim.Should().NotBeNull(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
userIdClaim!.Value.Should().Be(userId.ToString()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
user.Claims.Should().HaveCount(2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task OnAuthorizationAsync_CompleteValidFlow_ShouldNotSetResult() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Arrange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var userId = Guid.NewGuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var validToken = "complete-valid-token"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var filterContext = CreateFilterContext("Authorization", $"Bearer {validToken}"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService.Setup(x => x.ValidateAccessTokenAsync(validToken)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.ReturnsAsync(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_mockTokenService.Setup(x => x.GetUserIdFromTokenAsync(validToken)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.ReturnsAsync(userId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Act | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await _filter.OnAuthorizationAsync(filterContext); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Assert | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
filterContext.Result.Should().BeNull(); // No result means continue with request | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
filterContext.HttpContext.User.Identity!.IsAuthenticated.Should().BeTrue(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#endregion | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
빈 Authorization 헤더가 설정되지 않아 테스트가 의도대로 동작하지 않습니다
headerValue가 빈 문자열일 때 헤더가 아예 추가되지 않아 “빈 헤더” 시나리오가 “헤더 없음”과 동일하게 동작합니다. 빈 값도 설정되도록 조건을 완화해 주세요.
📝 Committable suggestion
🤖 Prompt for AI Agents