diff --git a/src/Api/Startup.cs b/src/Api/Startup.cs index d9ed03b23e..f23015cd3e 100644 --- a/src/Api/Startup.cs +++ b/src/Api/Startup.cs @@ -94,6 +94,11 @@ namespace Bit.Api policy.RequireAuthenticatedUser(); policy.RequireClaim(JwtClaimTypes.Scope, "api.licensing"); }); + config.AddPolicy("Organization", policy => + { + policy.RequireAuthenticatedUser(); + policy.RequireClaim(JwtClaimTypes.Scope, "api.organization"); + }); }); services.AddScoped(); diff --git a/src/Core/IdentityServer/ApiResources.cs b/src/Core/IdentityServer/ApiResources.cs index bdca86b62d..1a432bff1b 100644 --- a/src/Core/IdentityServer/ApiResources.cs +++ b/src/Core/IdentityServer/ApiResources.cs @@ -24,7 +24,8 @@ namespace Bit.Core.IdentityServer }), new ApiResource("internal", new string[] { JwtClaimTypes.Subject }), new ApiResource("api.push", new string[] { JwtClaimTypes.Subject }), - new ApiResource("api.licensing", new string[] { JwtClaimTypes.Subject }) + new ApiResource("api.licensing", new string[] { JwtClaimTypes.Subject }), + new ApiResource("api.organization", new string[] { JwtClaimTypes.Subject }) }; } } diff --git a/src/Core/IdentityServer/ClientStore.cs b/src/Core/IdentityServer/ClientStore.cs index 49eec9a6f5..e686409c4b 100644 --- a/src/Core/IdentityServer/ClientStore.cs +++ b/src/Core/IdentityServer/ClientStore.cs @@ -15,13 +15,16 @@ namespace Bit.Core.IdentityServer private static IDictionary _apiClients = StaticClients.GetApiClients(); private readonly IInstallationRepository _installationRepository; + private readonly IOrganizationRepository _organizationRepository; private readonly GlobalSettings _globalSettings; public ClientStore( IInstallationRepository installationRepository, + IOrganizationRepository organizationRepository, GlobalSettings globalSettings) { _installationRepository = installationRepository; + _organizationRepository = organizationRepository; _globalSettings = globalSettings; } @@ -72,6 +75,28 @@ namespace Bit.Core.IdentityServer } } } + else if(clientId.StartsWith("organization.")) + { + var idParts = clientId.Split('.'); + if(idParts.Length > 1 && Guid.TryParse(idParts[1], out var id)) + { + var org = await _organizationRepository.GetByIdAsync(id); + if(org != null) + { + return new Client + { + ClientId = $"organization.{org.Id}", + RequireClientSecret = true, + ClientSecrets = { new Secret(org.Id.ToString().Sha256()) }, // TODO: org.ApiKey + AllowedScopes = new string[] { "api.organization" }, + AllowedGrantTypes = GrantTypes.ClientCredentials, + AccessTokenLifetime = 3600 * 1, + Enabled = org.Enabled, // TODO: && org.UseApi + Claims = new List { new Claim(JwtClaimTypes.Subject, org.Id.ToString()) } + }; + } + } + } return _apiClients.ContainsKey(clientId) ? _apiClients[clientId] : null; }