mirror of
https://github.com/bitwarden/server.git
synced 2025-05-31 08:10:32 -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
|
#nullable enable
|
||||||
|
|
||||||
using Bit.Api.AdminConsole.Context;
|
|
||||||
using Bit.Core.Context;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
namespace Bit.Api.AdminConsole.Authorization;
|
namespace Bit.Api.AdminConsole.Authorization;
|
||||||
@ -12,8 +10,6 @@ namespace Bit.Api.AdminConsole.Authorization;
|
|||||||
/// determine whether the action is authorized.
|
/// determine whether the action is authorized.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class OrganizationRequirementHandler(
|
public class OrganizationRequirementHandler(
|
||||||
ICurrentContext currentContext,
|
|
||||||
IProviderOrganizationContext providerOrganizationContext,
|
|
||||||
IHttpContextAccessor httpContextAccessor)
|
IHttpContextAccessor httpContextAccessor)
|
||||||
: AuthorizationHandler<IOrganizationRequirement>
|
: AuthorizationHandler<IOrganizationRequirement>
|
||||||
{
|
{
|
||||||
@ -25,7 +21,8 @@ public class OrganizationRequirementHandler(
|
|||||||
throw new Exception("No organizationId found in route. IOrganizationRequirement cannot be used on this endpoint.");
|
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);
|
var authorized = await requirement.AuthorizeAsync(organizationId.Value, organizationClaims, providerOrganizationContext);
|
||||||
|
|
||||||
|
@ -257,10 +257,11 @@ public class Startup
|
|||||||
|
|
||||||
// Add authentication and authorization to the request pipeline.
|
// Add authentication and authorization to the request pipeline.
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
// Note: ICurrentContext is used in authorization middleware so it must be registered first
|
|
||||||
app.UseMiddleware<CurrentContextMiddleware>();
|
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
// Add current context
|
||||||
|
app.UseMiddleware<CurrentContextMiddleware>();
|
||||||
|
|
||||||
// Add endpoints to the request pipeline.
|
// Add endpoints to the request pipeline.
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
|
@ -512,7 +512,7 @@ public class CurrentContext : ICurrentContext
|
|||||||
return claims[type].FirstOrDefault()?.Value;
|
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)
|
bool hasClaim(string claimKey)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user