mirror of
https://github.com/bitwarden/server.git
synced 2026-06-01 12:26:46 -05:00
* Also decouple ProviderClientsController from Billing Team code * Also add noop authorize attribute where no additional authorization is required * Also remove unused ICurrentContext getters
155 lines
5.1 KiB
C#
155 lines
5.1 KiB
C#
using Bit.Api.AdminConsole.Authorization;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Xunit;
|
|
|
|
namespace Bit.Api.Test.Utilities;
|
|
|
|
public class ControllerAuthorizationTestHelpersTests
|
|
{
|
|
[Fact]
|
|
public void AssertAllHttpMethodsHaveAuthorization_ControllerMissingClassLevelAuthorize_Throws()
|
|
{
|
|
var exception = Assert.Throws<Xunit.Sdk.FailException>(() =>
|
|
ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization(
|
|
typeof(ControllerWithoutClassAuthorize)));
|
|
|
|
Assert.Contains("missing required class-level [Authorize] attribute", exception.Message);
|
|
Assert.Contains("ControllerWithoutClassAuthorize", exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void AssertAllHttpMethodsHaveAuthorization_MethodMissingAuthorization_Throws()
|
|
{
|
|
var exception = Assert.Throws<Xunit.Sdk.FailException>(() =>
|
|
ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization(
|
|
typeof(ControllerWithUnauthorizedMethod)));
|
|
|
|
Assert.Contains("3 HTTP action method(s) without method-level authorization", exception.Message);
|
|
Assert.Contains("GetUnauthorized ([HttpGet])", exception.Message);
|
|
Assert.Contains("PostUnauthorized ([HttpPost])", exception.Message);
|
|
Assert.Contains("PutUnauthorized ([HttpPut])", exception.Message);
|
|
Assert.Contains("ControllerWithUnauthorizedMethod", exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void AssertAllHttpMethodsHaveAuthorization_AllMethodsProperlyAuthorized_DoesNotThrow()
|
|
{
|
|
ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization(
|
|
typeof(ControllerWithProperAuthorization));
|
|
}
|
|
|
|
[Fact]
|
|
public void AssertAllHttpMethodsHaveAuthorization_MethodWithAllowAnonymous_DoesNotThrow()
|
|
{
|
|
ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization(
|
|
typeof(ControllerWithAllowAnonymous));
|
|
}
|
|
|
|
[Fact]
|
|
public void AssertAllHttpMethodsHaveAuthorization_MethodWithNoopAuthorize_DoesNotThrow()
|
|
{
|
|
ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization(
|
|
typeof(ControllerWithNoopAuthorize));
|
|
}
|
|
|
|
[Fact]
|
|
public void AssertAllHttpMethodsHaveAuthorization_ControllerWithNoHttpMethods_Throws()
|
|
{
|
|
var exception = Assert.Throws<Xunit.Sdk.FailException>(() =>
|
|
ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization(
|
|
typeof(ControllerWithNoHttpMethods)));
|
|
|
|
Assert.Contains("has no HTTP action methods", exception.Message);
|
|
}
|
|
|
|
// Controller missing class-level [Authorize]
|
|
private class ControllerWithoutClassAuthorize : ControllerBase
|
|
{
|
|
[HttpGet]
|
|
[CustomAuthorize]
|
|
public OkResult Get() => Ok();
|
|
}
|
|
|
|
// Controller with class-level [Authorize] but methods missing method-level authorization
|
|
[Authorize]
|
|
private class ControllerWithUnauthorizedMethod : ControllerBase
|
|
{
|
|
[HttpGet("authorized")]
|
|
[CustomAuthorize]
|
|
public OkResult GetAuthorized() => Ok();
|
|
|
|
[HttpGet("unauthorized")]
|
|
public OkResult GetUnauthorized() => Ok();
|
|
|
|
[HttpPost("unauthorized")]
|
|
public OkResult PostUnauthorized() => Ok();
|
|
|
|
[HttpPut("unauthorized")]
|
|
public OkResult PutUnauthorized() => Ok();
|
|
|
|
// Non-HTTP method should be ignored
|
|
public OkResult NonHttpMethod() => Ok();
|
|
}
|
|
|
|
// Controller with proper authorization on all methods
|
|
[Authorize]
|
|
private class ControllerWithProperAuthorization : ControllerBase
|
|
{
|
|
[HttpGet("custom")]
|
|
[CustomAuthorize]
|
|
public OkResult GetWithCustom() => Ok();
|
|
|
|
[HttpPost("custom")]
|
|
[CustomAuthorize]
|
|
public OkResult PostWithCustom() => Ok();
|
|
|
|
[HttpDelete("custom")]
|
|
[CustomAuthorize]
|
|
public OkResult DeleteWithCustom() => Ok();
|
|
}
|
|
|
|
// Controller with AllowAnonymous (which is valid method-level authorization)
|
|
[Authorize]
|
|
private class ControllerWithAllowAnonymous : ControllerBase
|
|
{
|
|
[HttpGet("anonymous")]
|
|
[AllowAnonymous]
|
|
public OkResult GetAnonymous() => Ok();
|
|
|
|
[HttpPost("protected")]
|
|
[CustomAuthorize]
|
|
public OkResult PostProtected() => Ok();
|
|
|
|
[HttpGet("mixed")]
|
|
[AllowAnonymous]
|
|
public OkResult GetMixed() => Ok();
|
|
}
|
|
|
|
// Controller with [NoopAuthorize] on a method (authenticated, no additional authz)
|
|
[Authorize]
|
|
private class ControllerWithNoopAuthorize : ControllerBase
|
|
{
|
|
[HttpGet("noop")]
|
|
[NoopAuthorize]
|
|
public OkResult GetWithNoop() => Ok();
|
|
|
|
[HttpPost("protected")]
|
|
[CustomAuthorize]
|
|
public OkResult PostProtected() => Ok();
|
|
}
|
|
|
|
// Controller with no HTTP methods
|
|
[Authorize]
|
|
private class ControllerWithNoHttpMethods : ControllerBase
|
|
{
|
|
public OkResult NotAnHttpMethod() => Ok();
|
|
public void AnotherNonHttpMethod() { }
|
|
}
|
|
|
|
// Custom authorize attribute for testing (mimics [Authorize<T>])
|
|
private class CustomAuthorizeAttribute : AuthorizeAttribute
|
|
{
|
|
}
|
|
}
|