From 4b870dab0bf4b9c8e0959e1d20ac7f22af19443e Mon Sep 17 00:00:00 2001 From: Jared Snider Date: Thu, 29 May 2025 17:10:04 -0400 Subject: [PATCH] PM-20532 - Update ProfileService.cs to add docs + add send client handling. --- src/Identity/IdentityServer/ProfileService.cs | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Identity/IdentityServer/ProfileService.cs b/src/Identity/IdentityServer/ProfileService.cs index 6d843aed76..ce491608b7 100644 --- a/src/Identity/IdentityServer/ProfileService.cs +++ b/src/Identity/IdentityServer/ProfileService.cs @@ -1,6 +1,7 @@ using System.Security.Claims; using Bit.Core.AdminConsole.Repositories; using Bit.Core.Context; +using Bit.Core.Enums; using Bit.Core.Identity; using Bit.Core.Repositories; using Bit.Core.Services; @@ -35,10 +36,23 @@ public class ProfileService : IProfileService _currentContext = currentContext; } - // TODO: this will be called for the SendAccessGrantValidator public async Task GetProfileDataAsync(ProfileDataRequestContext context) { var existingClaims = context.Subject.Claims; + + if (context.Client.ClientId == BitwardenClient.Send) + { + // preserve all claims that were already on context.Subject + // which includes the ones added by the SendAccessGrantValidator + context.IssuedClaims.AddRange(existingClaims); + return; + } + + // Whenever IdentityServer issues a new access token or services a UserInfo request, it calls + // GetProfileDataAsync to determine which claims to include in the token or response. + // In normal user identity scenarios, we have to look up the user to get their claims and update + // the issued claims collection as claim info can have changed since the last time the user logged in or the + // last time the token was issued. var newClaims = new List(); var user = await _userService.GetUserByPrincipalAsync(context.Subject); @@ -58,9 +72,12 @@ public class ProfileService : IProfileService } } - // filter out any of the new claims var existingClaimsToKeep = existingClaims - .Where(c => !c.Type.StartsWith("org") && + .Where(c => + // Drop any org claims + !c.Type.StartsWith("org") && + // If we have no new claims, then keep the existing claims + // If we have new claims, then keep the existing claim if it does not match a new claim type (newClaims.Count == 0 || !newClaims.Any(nc => nc.Type == c.Type))) .ToList(); @@ -75,6 +92,12 @@ public class ProfileService : IProfileService public async Task IsActiveAsync(IsActiveContext context) { + if (context.Client.ClientId == BitwardenClient.Send) + { + context.IsActive = true; + return; + } + // We add the security stamp claim to the persisted grant when we issue the refresh token. // IdentityServer will add this claim to the subject, and here we evaluate whether the security stamp that // was persisted matches the current security stamp of the user. If it does not match, then the user has performed