Files
server/src/Core/IdentityServer/ClientStore.cs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

179 lines
8.3 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Bit.Core.Context;
2018-08-15 18:43:26 -04:00
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Settings;
using Bit.Core.Utilities;
using IdentityModel;
using IdentityServer4.Models;
using IdentityServer4.Stores;
namespace Bit.Core.IdentityServer
{
public class ClientStore : IClientStore
{
private readonly IInstallationRepository _installationRepository;
2019-02-26 17:01:33 -05:00
private readonly IOrganizationRepository _organizationRepository;
private readonly IUserRepository _userRepository;
2018-08-15 18:43:26 -04:00
private readonly GlobalSettings _globalSettings;
2020-08-28 13:32:15 -04:00
private readonly StaticClientStore _staticClientStore;
private readonly ILicensingService _licensingService;
private readonly ICurrentContext _currentContext;
private readonly IOrganizationUserRepository _organizationUserRepository;
2021-06-30 09:35:26 +02:00
private readonly IProviderUserRepository _providerUserRepository;
private readonly IProviderOrganizationRepository _providerOrganizationRepository;
2018-08-15 18:43:26 -04:00
public ClientStore(
2018-08-15 18:43:26 -04:00
IInstallationRepository installationRepository,
2019-02-26 17:01:33 -05:00
IOrganizationRepository organizationRepository,
IUserRepository userRepository,
2020-08-28 13:32:15 -04:00
GlobalSettings globalSettings,
StaticClientStore staticClientStore,
ILicensingService licensingService,
ICurrentContext currentContext,
2021-06-30 09:35:26 +02:00
IOrganizationUserRepository organizationUserRepository,
IProviderUserRepository providerUserRepository,
IProviderOrganizationRepository providerOrganizationRepository)
{
_installationRepository = installationRepository;
2019-02-26 17:01:33 -05:00
_organizationRepository = organizationRepository;
_userRepository = userRepository;
2018-08-15 18:43:26 -04:00
_globalSettings = globalSettings;
2020-08-28 13:32:15 -04:00
_staticClientStore = staticClientStore;
_licensingService = licensingService;
_currentContext = currentContext;
_organizationUserRepository = organizationUserRepository;
2021-06-30 09:35:26 +02:00
_providerUserRepository = providerUserRepository;
_providerOrganizationRepository = providerOrganizationRepository;
}
public async Task<Client> FindClientByIdAsync(string clientId)
{
if (!_globalSettings.SelfHosted && clientId.StartsWith("installation."))
{
var idParts = clientId.Split('.');
if (idParts.Length > 1 && Guid.TryParse(idParts[1], out Guid id))
{
var installation = await _installationRepository.GetByIdAsync(id);
if (installation != null)
{
return new Client
{
ClientId = $"installation.{installation.Id}",
RequireClientSecret = true,
ClientSecrets = { new Secret(installation.Key.Sha256()) },
AllowedScopes = new string[] { "api.push", "api.licensing" },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AccessTokenLifetime = 3600 * 24,
Enabled = installation.Enabled,
2020-08-28 13:32:15 -04:00
Claims = new List<ClientClaim>
{
new ClientClaim(JwtClaimTypes.Subject, installation.Id.ToString())
}
};
}
}
}
else if (_globalSettings.SelfHosted && clientId.StartsWith("internal.") &&
2018-08-15 18:43:26 -04:00
CoreHelpers.SettingHasValue(_globalSettings.InternalIdentityKey))
{
var idParts = clientId.Split('.');
if (idParts.Length > 1)
2018-08-15 18:43:26 -04:00
{
var id = idParts[1];
if (!string.IsNullOrWhiteSpace(id))
2018-08-15 18:43:26 -04:00
{
return new Client
{
ClientId = $"internal.{id}",
RequireClientSecret = true,
ClientSecrets = { new Secret(_globalSettings.InternalIdentityKey.Sha256()) },
AllowedScopes = new string[] { "internal" },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AccessTokenLifetime = 3600 * 24,
Enabled = true,
2020-08-28 13:32:15 -04:00
Claims = new List<ClientClaim>
{
new ClientClaim(JwtClaimTypes.Subject, id)
}
2018-08-15 18:43:26 -04:00
};
}
}
}
else if (clientId.StartsWith("organization."))
2019-02-26 17:01:33 -05:00
{
var idParts = clientId.Split('.');
if (idParts.Length > 1 && Guid.TryParse(idParts[1], out var id))
2019-02-26 17:01:33 -05:00
{
var org = await _organizationRepository.GetByIdAsync(id);
if (org != null)
2019-02-26 17:01:33 -05:00
{
return new Client
{
ClientId = $"organization.{org.Id}",
RequireClientSecret = true,
2019-03-02 15:09:33 -05:00
ClientSecrets = { new Secret(org.ApiKey.Sha256()) },
2019-02-26 17:01:33 -05:00
AllowedScopes = new string[] { "api.organization" },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AccessTokenLifetime = 3600 * 1,
2019-03-02 15:09:33 -05:00
Enabled = org.Enabled && org.UseApi,
2020-08-28 13:32:15 -04:00
Claims = new List<ClientClaim>
{
new ClientClaim(JwtClaimTypes.Subject, org.Id.ToString())
}
2019-02-26 17:01:33 -05:00
};
}
}
}
else if (clientId.StartsWith("user."))
{
var idParts = clientId.Split('.');
if (idParts.Length > 1 && Guid.TryParse(idParts[1], out var id))
{
var user = await _userRepository.GetByIdAsync(id);
if (user != null)
{
var claims = new Collection<ClientClaim>()
{
new ClientClaim(JwtClaimTypes.Subject, user.Id.ToString()),
new ClientClaim(JwtClaimTypes.AuthenticationMethod, "Application", "external")
};
var orgs = await _currentContext.OrganizationMembershipAsync(_organizationUserRepository, user.Id);
2021-06-30 09:35:26 +02:00
var providers = await _currentContext.ProviderMembershipAsync(_providerUserRepository, user.Id);
var isPremium = await _licensingService.ValidateUserPremiumAsync(user);
2021-06-30 09:35:26 +02:00
foreach (var claim in CoreHelpers.BuildIdentityClaims(user, orgs, providers, isPremium))
{
var upperValue = claim.Value.ToUpperInvariant();
var isBool = upperValue == "TRUE" || upperValue == "FALSE";
claims.Add(isBool ?
new ClientClaim(claim.Key, claim.Value, ClaimValueTypes.Boolean) :
new ClientClaim(claim.Key, claim.Value)
);
}
return new Client
{
ClientId = clientId,
RequireClientSecret = true,
ClientSecrets = { new Secret(user.ApiKey.Sha256()) },
AllowedScopes = new string[] { "api" },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AccessTokenLifetime = 3600 * 1,
ClientClaimsPrefix = null,
Claims = claims
};
}
}
}
2020-08-28 13:32:15 -04:00
return _staticClientStore.ApiClients.ContainsKey(clientId) ?
_staticClientStore.ApiClients[clientId] : null;
}
}
}