public static Dictionary GetProcessedUserClaims()

in src/Core/Authorization/AuthorizationResolver.cs [500:565]


    public static Dictionary<string, string> GetProcessedUserClaims(HttpContext? context)
    {
        Dictionary<string, string> processedClaims = new();

        if (context is null)
        {
            return processedClaims;
        }

        Dictionary<string, List<Claim>> userClaims = GetAllAuthenticatedUserClaims(context);

        foreach ((string claimName, List<Claim> claimValues) in userClaims)
        {
            // Some identity providers (other than Entra ID) may emit a 'scope' claim as a JSON string array. dotnet will
            // create claim objects for each value in the array. DAB will honor that format
            // and processes the 'scope' claim objects as a JSON array serialized to a string.
            if (claimValues.Count > 1)
            {
                switch (claimValues.First().ValueType)
                {
                    case ClaimValueTypes.Boolean:
                        processedClaims.Add(claimName, value: JsonSerializer.Serialize(claimValues.Select(claim => bool.Parse(claim.Value))));
                        break;
                    case ClaimValueTypes.Integer:
                    case ClaimValueTypes.Integer32:
                        processedClaims.Add(claimName, value: JsonSerializer.Serialize(claimValues.Select(claim => int.Parse(claim.Value))));
                        break;
                    // Per Microsoft Docs: UInt32's CLS compliant alternative is Integer64
                    // https://learn.microsoft.com/dotnet/api/system.uint32#remarks
                    case ClaimValueTypes.UInteger32:
                    case ClaimValueTypes.Integer64:
                        processedClaims.Add(claimName, value: JsonSerializer.Serialize(claimValues.Select(claim => long.Parse(claim.Value))));
                        break;
                    // Per Microsoft Docs: UInt64's CLS compliant alternative is decimal
                    // https://learn.microsoft.com/dotnet/api/system.uint64#remarks
                    case ClaimValueTypes.UInteger64:
                        processedClaims.Add(claimName, value: JsonSerializer.Serialize(claimValues.Select(claim => decimal.Parse(claim.Value))));
                        break;
                    case ClaimValueTypes.Double:
                        processedClaims.Add(claimName, value: JsonSerializer.Serialize(claimValues.Select(claim => double.Parse(claim.Value))));
                        break;
                    case ClaimValueTypes.String:
                    case JsonClaimValueTypes.JsonNull:
                    case JsonClaimValueTypes.Json:
                    default:
                        string json = JsonSerializer.Serialize(claimValues.Select(claim => claim.Value));
                        processedClaims.Add(claimName, value: json);
                        break;
                }
            }
            else
            {
                // Remaining claims will be collected as string scalar values.
                // While Claim.ValueType may indicate the token value was not a string (int, bool),
                // resolving the actual type here would be a breaking change because 
                // DAB has historically sent single instance claims as value type string.
                // This block also accommodates Entra ID access tokens to avoid a breaking change because
                // the 'scp' claim is a space delimited string which is not broken up into separate claim objects
                // by dotnet. The Entra ID 'scp' claim should be passed to MSSQL's session context as-is.
                // https://learn.microsoft.com/entra/identity-platform/access-token-claims-reference#payload-claims
                processedClaims.Add(claimName, value: claimValues[0].Value);
            }
        }

        return processedClaims;
    }