mirror of
https://github.com/bitwarden/server
synced 2025-12-25 20:53:16 +00:00
* Add DynamicClientStore * Formatting * Fix Debug assertion * Make Identity internals visible to its unit tests * Add installation client provider tests * Add internal client provider tests * Add DynamicClientStore tests * Fix namespaces after merge * Format * Add docs and remove TODO comments * Use preferred prefix for API keys --------- Co-authored-by: Jared Snider <116684653+JaredSnider-Bitwarden@users.noreply.github.com>
83 lines
2.9 KiB
C#
83 lines
2.9 KiB
C#
#nullable enable
|
|
|
|
using System.Collections.ObjectModel;
|
|
using System.Security.Claims;
|
|
using Bit.Core.AdminConsole.Repositories;
|
|
using Bit.Core.Context;
|
|
using Bit.Core.Identity;
|
|
using Bit.Core.Repositories;
|
|
using Bit.Core.Services;
|
|
using Bit.Core.Utilities;
|
|
using Duende.IdentityServer.Models;
|
|
using IdentityModel;
|
|
|
|
namespace Bit.Identity.IdentityServer.ClientProviders;
|
|
|
|
public class UserClientProvider : IClientProvider
|
|
{
|
|
private readonly IUserRepository _userRepository;
|
|
private readonly ICurrentContext _currentContext;
|
|
private readonly ILicensingService _licensingService;
|
|
private readonly IOrganizationUserRepository _organizationUserRepository;
|
|
private readonly IProviderUserRepository _providerUserRepository;
|
|
|
|
public UserClientProvider(
|
|
IUserRepository userRepository,
|
|
ICurrentContext currentContext,
|
|
ILicensingService licensingService,
|
|
IOrganizationUserRepository organizationUserRepository,
|
|
IProviderUserRepository providerUserRepository)
|
|
{
|
|
_userRepository = userRepository;
|
|
_currentContext = currentContext;
|
|
_licensingService = licensingService;
|
|
_organizationUserRepository = organizationUserRepository;
|
|
_providerUserRepository = providerUserRepository;
|
|
}
|
|
|
|
public async Task<Client?> GetAsync(string identifier)
|
|
{
|
|
if (!Guid.TryParse(identifier, out var userId))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var user = await _userRepository.GetByIdAsync(userId);
|
|
if (user == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var claims = new Collection<ClientClaim>
|
|
{
|
|
new(JwtClaimTypes.Subject, user.Id.ToString()),
|
|
new(JwtClaimTypes.AuthenticationMethod, "Application", "external"),
|
|
new(Claims.Type, IdentityClientType.User.ToString()),
|
|
};
|
|
var orgs = await _currentContext.OrganizationMembershipAsync(_organizationUserRepository, user.Id);
|
|
var providers = await _currentContext.ProviderMembershipAsync(_providerUserRepository, user.Id);
|
|
var isPremium = await _licensingService.ValidateUserPremiumAsync(user);
|
|
foreach (var claim in CoreHelpers.BuildIdentityClaims(user, orgs, providers, isPremium))
|
|
{
|
|
var upperValue = claim.Value.ToUpperInvariant();
|
|
var isBool = upperValue is "TRUE" or "FALSE";
|
|
claims.Add(isBool
|
|
? new ClientClaim(claim.Key, claim.Value, ClaimValueTypes.Boolean)
|
|
: new ClientClaim(claim.Key, claim.Value)
|
|
);
|
|
}
|
|
|
|
return new Client
|
|
{
|
|
ClientId = $"user.{userId}",
|
|
RequireClientSecret = true,
|
|
ClientSecrets = { new Secret(user.ApiKey.Sha256()) },
|
|
AllowedScopes = new[] { "api" },
|
|
AllowedGrantTypes = GrantTypes.ClientCredentials,
|
|
AccessTokenLifetime = 3600 * 1,
|
|
ClientClaimsPrefix = null,
|
|
Claims = claims,
|
|
};
|
|
}
|
|
}
|