private static IDictionary ExtractClaims()

in wwauth/Google.Solutions.WWAuth/Data/JsonWebToken.cs [66:133]


        private static IDictionary<string, object> ExtractClaims(string jwt)
        {
            var jwtParts = jwt
                .ThrowIfNullOrEmpty(nameof(jwt))
                .Split('.');
            if (jwtParts.Length != 3)
            {
                throw new InvalidJwtException(
                    "JWT must consist of Header, Payload, and Signature");
            }

            //
            // Deserialize the body, which might contain nested objects.
            //
            var body = NewtonsoftJsonSerializer
                .Instance
                .Deserialize<Dictionary<string, object>>(
                    Encoding.UTF8.GetString(UrlSafeBase64.Decode(jwtParts[1])));

            //
            // Flatten the body into a key/value pair list:
            //
            //   assertion.claim
            //   assertion.claim.nestedclaim
            //   ...
            //
            // Treat multi-valued attributes as arrays:
            //
            //   assertion.claim[<index>]
            //
            // This is the syntax used by pool provider mappings.
            //

            var claims = new Dictionary<string, object>();

            void Visit(string name, object value)
            {
                if (value is JArray jarray)
                {
                    for (int i = 0; i < jarray.Count; i++)
                    {
                        Visit($"{name}[{i}]", jarray[i]);
                    }
                }
                else if (value is JObject jobject)
                {
                    foreach (var property in jobject)
                    {
                        Visit($"{name}.{property.Key}", property.Value);
                    }
                }
                else if (value is JValue jvalue)
                {
                    claims.Add(name, jvalue.Value);
                }
                else
                {
                    claims.Add(name, value);
                }
            }

            foreach (var claim in body)
            {
                Visit($"assertion.{claim.Key}", claim.Value);
            }

            return claims;
        }