mirror of
https://github.com/bitwarden/server.git
synced 2025-04-04 20:50:21 -05:00
WIP: parsing claims from context
This commit is contained in:
parent
3ec9e318b1
commit
ef30805d0e
76
src/Api/AdminConsole/Authorization/ClaimsExtensions.cs
Normal file
76
src/Api/AdminConsole/Authorization/ClaimsExtensions.cs
Normal file
@ -0,0 +1,76 @@
|
||||
#nullable enable
|
||||
|
||||
using System.Security.Claims;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Identity;
|
||||
|
||||
namespace Bit.Api.AdminConsole.Authorization;
|
||||
|
||||
public static class ClaimsExtensions
|
||||
{
|
||||
public static CurrentContextOrganization? GetCurrentContextOrganization(this ClaimsPrincipal user, Guid organizationId)
|
||||
{
|
||||
var claimsDict = user.Claims
|
||||
.GroupBy(c => c.Type)
|
||||
.ToDictionary(c => c.Key, c => c.Select(v => v));
|
||||
|
||||
var accessSecretsManager = claimsDict.TryGetValue(Claims.SecretsManagerAccess, out var value)
|
||||
? value
|
||||
.Where(s => Guid.TryParse(s.Value, out _))
|
||||
.Select(s => new Guid(s.Value))
|
||||
.ToHashSet()
|
||||
: [];
|
||||
|
||||
var role = claimsDict.GetRoleForOrganizationId(organizationId);
|
||||
if (!role.HasValue)
|
||||
{
|
||||
// Not an organization member
|
||||
return null;
|
||||
}
|
||||
|
||||
return new CurrentContextOrganization
|
||||
{
|
||||
Id = organizationId,
|
||||
Type = role.Value,
|
||||
AccessSecretsManager = accessSecretsManager.Contains(organizationId),
|
||||
Permissions = role == OrganizationUserType.Custom
|
||||
? CurrentContext.SetOrganizationPermissionsFromClaims(organizationId.ToString(), claimsDict)
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
private static bool ContainsOrganizationId(this Dictionary<string, IEnumerable<Claim>> claimsDict, string claimType,
|
||||
Guid organizationId)
|
||||
=> claimsDict.TryGetValue(claimType, out var claimValue) &&
|
||||
claimValue.Any(c => c.Value.EqualsGuid(organizationId));
|
||||
|
||||
private static OrganizationUserType? GetRoleForOrganizationId(this Dictionary<string, IEnumerable<Claim>> claimsDict,
|
||||
Guid organizationId)
|
||||
{
|
||||
if (claimsDict.ContainsOrganizationId(Claims.OrganizationOwner, organizationId))
|
||||
{
|
||||
return OrganizationUserType.Owner;
|
||||
}
|
||||
|
||||
if (claimsDict.ContainsOrganizationId(Claims.OrganizationAdmin, organizationId))
|
||||
{
|
||||
return OrganizationUserType.Admin;
|
||||
}
|
||||
|
||||
if (claimsDict.ContainsOrganizationId(Claims.OrganizationCustom, organizationId))
|
||||
{
|
||||
return OrganizationUserType.Custom;
|
||||
}
|
||||
|
||||
if (claimsDict.ContainsOrganizationId(Claims.OrganizationUser, organizationId))
|
||||
{
|
||||
return OrganizationUserType.User;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool EqualsGuid(this string value, Guid guid)
|
||||
=> Guid.TryParse(value, out var parsedValue) && parsedValue == guid;
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
#nullable enable
|
||||
|
||||
using Bit.Api.AdminConsole.Context;
|
||||
using Bit.Core.Context;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Bit.Api.AdminConsole.Authorization;
|
||||
@ -12,8 +10,6 @@ namespace Bit.Api.AdminConsole.Authorization;
|
||||
/// determine whether the action is authorized.
|
||||
/// </summary>
|
||||
public class OrganizationRequirementHandler(
|
||||
ICurrentContext currentContext,
|
||||
IProviderOrganizationContext providerOrganizationContext,
|
||||
IHttpContextAccessor httpContextAccessor)
|
||||
: AuthorizationHandler<IOrganizationRequirement>
|
||||
{
|
||||
@ -25,7 +21,8 @@ public class OrganizationRequirementHandler(
|
||||
throw new Exception("No organizationId found in route. IOrganizationRequirement cannot be used on this endpoint.");
|
||||
}
|
||||
|
||||
var organizationClaims = currentContext.GetOrganization(organizationId.Value);
|
||||
var organizationClaims = context.User.GetCurrentContextOrganization(organizationId.Value);
|
||||
var providerOrganizationContext = null; // TODO
|
||||
|
||||
var authorized = await requirement.AuthorizeAsync(organizationId.Value, organizationClaims, providerOrganizationContext);
|
||||
|
||||
|
@ -257,10 +257,11 @@ public class Startup
|
||||
|
||||
// Add authentication and authorization to the request pipeline.
|
||||
app.UseAuthentication();
|
||||
// Note: ICurrentContext is used in authorization middleware so it must be registered first
|
||||
app.UseMiddleware<CurrentContextMiddleware>();
|
||||
app.UseAuthorization();
|
||||
|
||||
// Add current context
|
||||
app.UseMiddleware<CurrentContextMiddleware>();
|
||||
|
||||
// Add endpoints to the request pipeline.
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
|
@ -512,7 +512,7 @@ public class CurrentContext : ICurrentContext
|
||||
return claims[type].FirstOrDefault()?.Value;
|
||||
}
|
||||
|
||||
private Permissions SetOrganizationPermissionsFromClaims(string organizationId, Dictionary<string, IEnumerable<Claim>> claimsDict)
|
||||
public static Permissions SetOrganizationPermissionsFromClaims(string organizationId, Dictionary<string, IEnumerable<Claim>> claimsDict)
|
||||
{
|
||||
bool hasClaim(string claimKey)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user