public virtual UserInfo RecoverUserInfoFromJwtPayload(JwtPayload jwtPayload) { var result = new UserInfo(); result.Name = jwtPayload["name"] as string ?? throw new InvalidOperationException($"id_token incompleto: a propriedade 'name' não foi encontrada no token"); string foundKey = jwtPayload.Keys.FirstOrDefault(x => PossibleUsernameKeys.Contains(x)) ?? throw new InvalidOperationException($"id_token incompleto: uma das propriedades {string.Join(", ", PossibleUsernameKeys.Select(x => $"'{x}'"))} não foram encontradas no token"); result.UserName = jwtPayload[foundKey] as string; if (jwtPayload.ContainsKey("email")) { result.Email = jwtPayload["email"] as string; } else if (result.UserName.Contains("@")) { result.Email = result.UserName; } else { throw new InvalidOperationException("id_token incompleto: a propriedade 'email' não foi encontrada no token"); } if (jwtPayload.ContainsKey("groups")) { JArray rawGroups = jwtPayload["groups"] as JArray ?? throw new InvalidOperationException($"id_token incompleto: a propriedade 'groups' não foi encontrada no token"); result.Groups = TranslateGroupNames(rawGroups.Values <string>().ToList()); } return(result); }
// We need to handle json objects ourself as this isn't directly supported by JwtSecurityHandler yet private static JwtPayload AddJsonToPayload(JwtPayload payload, IEnumerable <Claim> jsonClaims) { var jsonTokens = jsonClaims.Select(x => new { x.Type, JsonValue = JRaw.Parse(x.Value) }).ToArray(); var jsonObjects = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Object).ToArray(); var jsonObjectGroups = jsonObjects.GroupBy(x => x.Type).ToArray(); foreach (var group in jsonObjectGroups) { if (payload.ContainsKey(group.Key)) { throw new IncompatibleClaimTypesException(string.Format("Can't add two claims where one is a JSON object and the other is not a JSON object ({0})", group.Key)); } if (group.Skip(1).Any()) { // add as array payload.Add(group.Key, group.Select(x => x.JsonValue).ToArray()); } else { // add just one payload.Add(group.Key, group.First().JsonValue); } } var jsonArrays = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Array).ToArray(); var jsonArrayGroups = jsonArrays.GroupBy(x => x.Type).ToArray(); foreach (var group in jsonArrayGroups) { if (payload.ContainsKey(group.Key)) { throw new IncompatibleClaimTypesException(string.Format("Can't add two claims where one is a JSON array and the other is not a JSON array ({0})", group.Key)); } var newArr = new List <JToken>(); foreach (var arrays in group) { var arr = (JArray)arrays.JsonValue; newArr.AddRange(arr); } // add just one array for the group/key/claim type payload.Add(group.Key, newArr.ToArray()); } var unsupportedJsonTokens = jsonTokens.Except(jsonObjects).Except(jsonArrays); var unsupportedJsonClaimTypes = unsupportedJsonTokens.Select(x => x.Type).Distinct(); if (unsupportedJsonClaimTypes.Any()) { var unsupportedClaimTypes = unsupportedJsonClaimTypes.Aggregate((x, y) => x + ", " + y); throw new UnsupportedJsonClaimTypeException($"Unsupported JSON type for claim types: {unsupportedClaimTypes}"); } return(payload); }
public static void SetClaimValue <T>(this JwtPayload payload, string type, T value) { if (payload.ContainsKey(type)) { payload.Remove(type); } if (typeof(T) == typeof(string)) { var stringValue = value?.ToString(); if (!string.IsNullOrWhiteSpace(stringValue)) { payload.AddClaim(new Claim(type, stringValue, ClaimValueTypes.String)); } } else if (typeof(T) == typeof(int)) { payload.AddClaim(new Claim(type, value.ToString(), ClaimValueTypes.Integer)); } else if (typeof(T).IsArray) { payload.AddClaim(new Claim(type, JsonConvert.SerializeObject(value, Settings), JsonClaimValueTypes.JsonArray)); } else { var json = JsonConvert.SerializeObject(value, Settings); payload.AddClaim(new Claim(type, json, JsonClaimValueTypes.Json)); } }
public static string Val(this JwtPayload payload, string key) { if (payload.ContainsKey(key)) { return(payload[key].ToString()); } return(""); }
/// <summary> /// /// </summary> /// <param name="jwtPayload"></param> /// <returns></returns> public static (string hashType, string bodyHash) GetBodyHashInfo(JwtPayload jwtPayload) { string hashType = string.Empty; string bodyHash = string.Empty; if (jwtPayload.ContainsKey(HASHTYPE_CLAIM_NAME)) { hashType = jwtPayload[HASHTYPE_CLAIM_NAME].ToString(); } if (jwtPayload.ContainsKey(BODYHASH_CLAIM_NAME)) { bodyHash = jwtPayload[BODYHASH_CLAIM_NAME].ToString(); } return(hashType, bodyHash); }
/// <summary> /// Creates the JWT payload /// </summary> /// <param name="token">The token.</param> /// <returns>The JWT payload</returns> protected virtual JwtPayload CreatePayload(Token token) { var payload = new JwtPayload( token.Issuer, token.Audience, null, DateTimeHelper.UtcNow, DateTimeHelper.UtcNow.AddSeconds(token.Lifetime)); var amrClaims = token.Claims.Where(x => x.Type == Constants.ClaimTypes.AuthenticationMethod); var jsonClaims = token.Claims.Where(x => x.ValueType == Constants.ClaimValueTypes.Json); var normalClaims = token.Claims.Except(amrClaims).Except(jsonClaims); payload.AddClaims(normalClaims); // deal with amr var amrValues = amrClaims.Select(x => x.Value).Distinct().ToArray(); if (amrValues.Any()) { payload.Add(Constants.ClaimTypes.AuthenticationMethod, amrValues); } // deal with json types // calling ToArray() to trigger JSON parsing once and so later // collection identity comparisons work for the anonymous type var jsonTokens = jsonClaims.Select(x => new { x.Type, JsonValue = JRaw.Parse(x.Value) }).ToArray(); var jsonObjects = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Object).ToArray(); var jsonObjectGroups = jsonObjects.GroupBy(x=>x.Type).ToArray(); foreach(var group in jsonObjectGroups) { if (payload.ContainsKey(group.Key)) { throw new Exception(String.Format("Can't add two claims where one is a JSON object and the other is not a JSON object ({0})", group.Key)); } if (group.Skip(1).Any()) { // add as array payload.Add(group.Key, group.Select(x=>x.JsonValue).ToArray()); } else { // add just one payload.Add(group.Key, group.First().JsonValue); } } var jsonArrays = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Array).ToArray(); var jsonArrayGroups = jsonArrays.GroupBy(x=>x.Type).ToArray(); foreach (var group in jsonArrayGroups) { if (payload.ContainsKey(group.Key)) { throw new Exception(String.Format("Can't add two claims where one is a JSON array and the other is not a JSON array ({0})", group.Key)); } List<JToken> newArr = new List<JToken>(); foreach(var arrays in group) { var arr = (JArray)arrays.JsonValue; newArr.AddRange(arr); } // add just one array for the group/key/claim type payload.Add(group.Key, newArr.ToArray()); } var unsupportedJsonTokens = jsonTokens.Except(jsonObjects).Except(jsonArrays); var unsupportedJsonClaimTypes = unsupportedJsonTokens.Select(x => x.Type).Distinct(); if (unsupportedJsonClaimTypes.Any()) { throw new Exception(String.Format("Unsupported JSON type for claim types: {0}", unsupportedJsonClaimTypes.Aggregate((x, y) => x + ", " + y))); } return payload; }
/// <summary> /// Creates the JWT payload /// </summary> /// <param name="token">The token.</param> /// <returns>The JWT payload</returns> protected virtual Task <JwtPayload> CreatePayloadAsync(Token token) { var payload = new JwtPayload( token.Issuer, null, null, IdentityServerDateTime.UtcNow, IdentityServerDateTime.UtcNow.AddSeconds(token.Lifetime)); foreach (var aud in token.Audiences) { payload.AddClaim(new Claim(JwtClaimTypes.Audience, aud)); } var amrClaims = token.Claims.Where(x => x.Type == JwtClaimTypes.AuthenticationMethod); var scopeClaims = token.Claims.Where(x => x.Type == JwtClaimTypes.Scope); var jsonClaims = token.Claims.Where(x => x.ValueType == IdentityServerConstants.ClaimValueTypes.Json); var normalClaims = token.Claims .Except(amrClaims) .Except(jsonClaims) .Except(scopeClaims); payload.AddClaims(normalClaims); // scope claims if (!scopeClaims.IsNullOrEmpty()) { var scopeValues = scopeClaims.Select(x => x.Value).ToArray(); payload.Add(JwtClaimTypes.Scope, scopeValues); } // amr claims if (!amrClaims.IsNullOrEmpty()) { var amrValues = amrClaims.Select(x => x.Value).Distinct().ToArray(); payload.Add(JwtClaimTypes.AuthenticationMethod, amrValues); } // deal with json types // calling ToArray() to trigger JSON parsing once and so later // collection identity comparisons work for the anonymous type var jsonTokens = jsonClaims.Select(x => new { x.Type, JsonValue = JRaw.Parse(x.Value) }).ToArray(); var jsonObjects = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Object).ToArray(); var jsonObjectGroups = jsonObjects.GroupBy(x => x.Type).ToArray(); foreach (var group in jsonObjectGroups) { if (payload.ContainsKey(group.Key)) { throw new Exception(String.Format("Can't add two claims where one is a JSON object and the other is not a JSON object ({0})", group.Key)); } if (group.Skip(1).Any()) { // add as array payload.Add(group.Key, group.Select(x => x.JsonValue).ToArray()); } else { // add just one payload.Add(group.Key, group.First().JsonValue); } } var jsonArrays = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Array).ToArray(); var jsonArrayGroups = jsonArrays.GroupBy(x => x.Type).ToArray(); foreach (var group in jsonArrayGroups) { if (payload.ContainsKey(group.Key)) { throw new Exception(String.Format("Can't add two claims where one is a JSON array and the other is not a JSON array ({0})", group.Key)); } List <JToken> newArr = new List <JToken>(); foreach (var arrays in group) { var arr = (JArray)arrays.JsonValue; newArr.AddRange(arr); } // add just one array for the group/key/claim type payload.Add(group.Key, newArr.ToArray()); } var unsupportedJsonTokens = jsonTokens.Except(jsonObjects).Except(jsonArrays); var unsupportedJsonClaimTypes = unsupportedJsonTokens.Select(x => x.Type).Distinct(); if (unsupportedJsonClaimTypes.Any()) { throw new Exception(String.Format("Unsupported JSON type for claim types: {0}", unsupportedJsonClaimTypes.Aggregate((x, y) => x + ", " + y))); } return(Task.FromResult(payload)); }
/// <summary> /// Turns a token object into JWT payload /// </summary> /// <param name="token">The token</param> /// <returns>Serialized JWT payload</returns> public static string CreateJwtPayload(this Token token) { var payload = new JwtPayload( token.Issuer, token.Audience, null, token.CreationTime.UtcDateTime, token.CreationTime.AddSeconds(token.Lifetime).UtcDateTime); var amrClaims = token.Claims.Where(x => x.Type == Constants.ClaimTypes.AuthenticationMethod); var jsonClaims = token.Claims.Where(x => x.ValueType == Constants.ClaimValueTypes.Json); var normalClaims = token.Claims.Except(amrClaims).Except(jsonClaims); payload.AddClaims(normalClaims); // deal with amr var amrValues = amrClaims.Select(x => x.Value).Distinct().ToArray(); if (amrValues.Any()) { payload.Add(Constants.ClaimTypes.AuthenticationMethod, amrValues); } // deal with json types // calling ToArray() to trigger JSON parsing once and so later // collection identity comparisons work for the anonymous type var jsonTokens = jsonClaims.Select(x => new { x.Type, JsonValue = JRaw.Parse(x.Value) }).ToArray(); var jsonObjects = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Object).ToArray(); var jsonObjectGroups = jsonObjects.GroupBy(x => x.Type).ToArray(); foreach (var group in jsonObjectGroups) { if (payload.ContainsKey(group.Key)) { throw new Exception(String.Format("Can't add two claims where one is a JSON object and the other is not a JSON object ({0})", group.Key)); } if (group.Skip(1).Any()) { // add as array payload.Add(group.Key, group.Select(x => x.JsonValue).ToArray()); } else { // add just one payload.Add(group.Key, group.First().JsonValue); } } var jsonArrays = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Array).ToArray(); var jsonArrayGroups = jsonArrays.GroupBy(x => x.Type).ToArray(); foreach (var group in jsonArrayGroups) { if (payload.ContainsKey(group.Key)) { throw new Exception(String.Format("Can't add two claims where one is a JSON array and the other is not a JSON array ({0})", group.Key)); } List <JToken> newArr = new List <JToken>(); foreach (var arrays in group) { var arr = (JArray)arrays.JsonValue; newArr.AddRange(arr); } // add just one array for the group/key/claim type payload.Add(group.Key, newArr.ToArray()); } var unsupportedJsonTokens = jsonTokens.Except(jsonObjects).Except(jsonArrays); var unsupportedJsonClaimTypes = unsupportedJsonTokens.Select(x => x.Type).Distinct(); if (unsupportedJsonClaimTypes.Any()) { throw new Exception(String.Format("Unsupported JSON type for claim types: {0}", unsupportedJsonClaimTypes.Aggregate((x, y) => x + ", " + y))); } return(payload.SerializeToJson()); }
/// <summary> /// Creates the default JWT payload. /// </summary> /// <param name="token">The token.</param> /// <param name="clock">The clock.</param> /// <param name="options">The options</param> /// <param name="logger">The logger.</param> /// <returns></returns> /// <exception cref="Exception"> /// </exception> public static JwtPayload CreateJwtPayload(this Token token, ISystemClock clock, IdentityServerOptions options, ILogger logger) { var payload = new JwtPayload( token.Issuer, null, null, clock.UtcNow.UtcDateTime, clock.UtcNow.UtcDateTime.AddSeconds(token.Lifetime)); foreach (var aud in token.Audiences) { payload.AddClaim(new Claim(JwtClaimTypes.Audience, aud)); } var amrClaims = token.Claims.Where(x => x.Type == JwtClaimTypes.AuthenticationMethod).ToArray(); var scopeClaims = token.Claims.Where(x => x.Type == JwtClaimTypes.Scope).ToArray(); var jsonClaims = token.Claims.Where(x => x.ValueType == IdentityServerConstants.ClaimValueTypes.Json).ToList(); // add confirmation claim if present (it's JSON valued) if (token.Confirmation.IsPresent()) { jsonClaims.Add(new Claim(JwtClaimTypes.Confirmation, token.Confirmation, IdentityServerConstants.ClaimValueTypes.Json)); } var normalClaims = token.Claims .Except(amrClaims) .Except(jsonClaims) .Except(scopeClaims); payload.AddClaims(normalClaims); // scope claims if (!scopeClaims.IsNullOrEmpty()) { var scopeValues = scopeClaims.Select(x => x.Value).ToArray(); if (options.EmitScopesAsSpaceDelimitedStringInJwt) { payload.Add(JwtClaimTypes.Scope, string.Join(" ", scopeValues)); } else { payload.Add(JwtClaimTypes.Scope, scopeValues); } } // amr claims if (!amrClaims.IsNullOrEmpty()) { var amrValues = amrClaims.Select(x => x.Value).Distinct().ToArray(); payload.Add(JwtClaimTypes.AuthenticationMethod, amrValues); } // deal with json types // calling ToArray() to trigger JSON parsing once and so later // collection identity comparisons work for the anonymous type try { var jsonTokens = jsonClaims.Select(x => new { x.Type, JsonValue = JRaw.Parse(x.Value) }).ToArray(); var jsonObjects = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Object).ToArray(); var jsonObjectGroups = jsonObjects.GroupBy(x => x.Type).ToArray(); foreach (var group in jsonObjectGroups) { if (payload.ContainsKey(group.Key)) { throw new Exception($"Can't add two claims where one is a JSON object and the other is not a JSON object ({group.Key})"); } if (group.Skip(1).Any()) { // add as array payload.Add(group.Key, group.Select(x => x.JsonValue).ToArray()); } else { // add just one payload.Add(group.Key, group.First().JsonValue); } } var jsonArrays = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Array).ToArray(); var jsonArrayGroups = jsonArrays.GroupBy(x => x.Type).ToArray(); foreach (var group in jsonArrayGroups) { if (payload.ContainsKey(group.Key)) { throw new Exception( $"Can't add two claims where one is a JSON array and the other is not a JSON array ({group.Key})"); } var newArr = new List <JToken>(); foreach (var arrays in group) { var arr = (JArray)arrays.JsonValue; newArr.AddRange(arr); } // add just one array for the group/key/claim type payload.Add(group.Key, newArr.ToArray()); } var unsupportedJsonTokens = jsonTokens.Except(jsonObjects).Except(jsonArrays).ToArray(); var unsupportedJsonClaimTypes = unsupportedJsonTokens.Select(x => x.Type).Distinct().ToArray(); if (unsupportedJsonClaimTypes.Any()) { throw new Exception( $"Unsupported JSON type for claim types: {unsupportedJsonClaimTypes.Aggregate((x, y) => x + ", " + y)}"); } return(payload); } catch (Exception ex) { logger.LogCritical(ex, "Error creating a JSON valued claim"); throw; } }