mirror of
https://github.com/bitwarden/server
synced 2025-12-22 11:13:27 +00:00
[PM-19585] Use Authorize attributes for simple role authorization (#5555)
- Add Authorize<T> attribute - Add IOrganizationRequirement and example implementation - Add OrganizationRequirementHandler - Add extension methods (replacing ICurrentContext) - Move custom permissions claim definitions --- Co-authored-by: Justin Baur <19896123+justindbaur@users.noreply.github.com> Co-authored-by: ✨ Audrey ✨ <ajensen@bitwarden.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
#nullable enable
|
||||
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Bit.Api.AdminConsole.Authorization;
|
||||
|
||||
/// <summary>
|
||||
/// Handles any requirement that implements <see cref="IOrganizationRequirement"/>.
|
||||
/// Retrieves the Organization ID from the route and then passes it to the requirement's AuthorizeAsync callback to
|
||||
/// determine whether the action is authorized.
|
||||
/// </summary>
|
||||
public class OrganizationRequirementHandler(
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IProviderUserRepository providerUserRepository,
|
||||
IUserService userService)
|
||||
: AuthorizationHandler<IOrganizationRequirement>
|
||||
{
|
||||
public const string NoHttpContextError = "This method should only be called in the context of an HTTP Request.";
|
||||
public const string NoUserIdError = "This method should only be called on the private api with a logged in user.";
|
||||
|
||||
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, IOrganizationRequirement requirement)
|
||||
{
|
||||
var httpContext = httpContextAccessor.HttpContext;
|
||||
if (httpContext == null)
|
||||
{
|
||||
throw new InvalidOperationException(NoHttpContextError);
|
||||
}
|
||||
|
||||
var organizationId = httpContext.GetOrganizationId();
|
||||
var organizationClaims = httpContext.User.GetCurrentContextOrganization(organizationId);
|
||||
|
||||
var userId = userService.GetProperUserId(httpContext.User);
|
||||
if (userId == null)
|
||||
{
|
||||
throw new InvalidOperationException(NoUserIdError);
|
||||
}
|
||||
|
||||
Task<bool> IsProviderUserForOrg() => httpContext.IsProviderUserForOrgAsync(providerUserRepository, userId.Value, organizationId);
|
||||
|
||||
var authorized = await requirement.AuthorizeAsync(organizationClaims, IsProviderUserForOrg);
|
||||
|
||||
if (authorized)
|
||||
{
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user