public void CreateAndValidateTokens_MultipleX5C() { List<string> errors = new List<string>(); var handler = new JwtSecurityTokenHandler(); var payload = new JwtPayload(); var header = new JwtHeader(); payload.AddClaims(ClaimSets.MultipleAudiences(IdentityUtilities.DefaultIssuer, IdentityUtilities.DefaultIssuer)); List<string> x5cs = new List<string> { "x5c1", "x5c2" }; header.Add(JwtHeaderParameterNames.X5c, x5cs); var jwtToken = new JwtSecurityToken(header, payload); var jwt = handler.WriteToken(jwtToken); var validationParameters = new TokenValidationParameters { RequireExpirationTime = false, RequireSignedTokens = false, ValidateAudience = false, ValidateIssuer = false, ValidateLifetime = false, }; SecurityToken validatedSecurityToken = null; var cp = handler.ValidateToken(jwt, validationParameters, out validatedSecurityToken); JwtSecurityToken validatedJwt = validatedSecurityToken as JwtSecurityToken; object x5csInHeader = validatedJwt.Header[JwtHeaderParameterNames.X5c]; if (x5csInHeader == null) { errors.Add("1: validatedJwt.Header[JwtHeaderParameterNames.X5c]"); } else { var list = x5csInHeader as IEnumerable<object>; if ( list == null ) { errors.Add("2: var list = x5csInHeader as IEnumerable<object>; is NULL."); } int num = 0; foreach(var str in list) { num++; if (!(str is string)) { errors.Add("3: str is not string, is:" + str.ToString()); } } if (num != x5cs.Count) { errors.Add("4: num != x5cs.Count. num: " + num.ToString() + "x5cs.Count: " + x5cs.Count.ToString()); } } // make sure we can still validate with existing logic. header = new JwtHeader(KeyingMaterial.DefaultAsymmetricSigningCreds_2048_RsaSha2_Sha2); header.Add(JwtHeaderParameterNames.X5c, x5cs); jwtToken = new JwtSecurityToken(header, payload); jwt = handler.WriteToken(jwtToken); validationParameters.IssuerSigningToken = KeyingMaterial.DefaultAsymmetricX509Token_2048; validationParameters.RequireSignedTokens = true; validatedSecurityToken = null; cp = handler.ValidateToken(jwt, validationParameters, out validatedSecurityToken); TestUtilities.AssertFailIfErrors(MethodInfo.GetCurrentMethod().Name, errors); }
public JsonWebToken Create(string userId, string userRole, bool isSignUp) { var nowUtc = DateTime.UtcNow; var expires = nowUtc.AddMinutes(_options.ExpiryMinutes); var centuryBegin = new DateTime(1970, 1, 1).ToUniversalTime(); var exp = (long)(new TimeSpan(expires.Ticks - centuryBegin.Ticks).TotalSeconds); var iat = (long)(new TimeSpan(nowUtc.Ticks - centuryBegin.Ticks).TotalSeconds); var claims = new[] { new Claim(JwtRegisteredClaimNames.UniqueName, userId.ToString()), new Claim(ClaimTypes.Role, userRole) }; var payload = new JwtPayload { { "userId", userId }, { "iss", _options.Issuer }, { "iat", iat }, { "exp", exp }, { "unique_name", userId }, { "userrole", userRole } }; payload.AddClaims(claims); var jwt = new JwtSecurityToken(_jwtHeader, payload); var token = _jwtSecurityTokenHandler.WriteToken(jwt); return(new JsonWebToken { Token = token, Expires = exp, UserRole = userRole }); }
public string Generate(Roles roles = Roles.Admin, string?name = default, TimeSpan?expiry = default) { var expirySeconds = (int)DateTime.UtcNow .Add(expiry ?? _defaultExpiry) .Subtract(DateTime.UnixEpoch) .TotalSeconds; var payload = new JwtPayload { ["exp"] = expirySeconds, ["iss"] = _issuer, ["aud"] = _audience, }; payload.AddClaims(from r in roles.Expand() let s = r.ToString("G") let c = new Claim(ClaimTypes.Role, s) select c); if (!string.IsNullOrWhiteSpace(name)) { var claim = new Claim(ClaimTypes.NameIdentifier, name); payload.AddClaim(claim); } var secToken = new JwtSecurityToken(_header, payload); var handler = new JwtSecurityTokenHandler(); return(handler.WriteToken(secToken)); }
public Task <string> CreateJwt(ClaimsIdentity claimsIdentity) { var nowUtc = DateTime.UtcNow; var expires = nowUtc.AddMinutes(_settings.TokenExpiryMinutes); var centuryBegin = new DateTime(1970, 1, 1); var exp = (long)(new TimeSpan(expires.Ticks - centuryBegin.Ticks).TotalSeconds); var now = (long)(new TimeSpan(nowUtc.Ticks - centuryBegin.Ticks).TotalSeconds); var payload = new JwtPayload { { "sub", claimsIdentity.Name }, { "unique_name", claimsIdentity.Name }, { "iss", _settings.Issuer }, { "aud", _settings.Audience }, { "iat", now }, { "nbf", now }, { "exp", exp }, { "jti", Guid.NewGuid().ToString("N") } }; payload.AddClaims(claimsIdentity.Claims.Where(_ => _.Type.Equals(ClaimTypes.Role)).ToList()); var jwtHeader = new JwtHeader(_signingCredentials); var jwt = new JwtSecurityToken(jwtHeader, payload); var jwtHandler = new JwtSecurityTokenHandler(); return(Task.FromResult(jwtHandler.WriteToken(jwt))); }
/// <summary> /// create payload of jwt /// contains: iss, aud, iat, nbf, exp, viewclaims, username /// </summary> /// <param name="username">username of user</param> /// <param name="exptime">experation time of token</param> /// <param name="type">user type, either admin or general</param> /// <returns></returns> public JwtPayload CreatePayload(string username, int exptime = 20)//, string type, int exptime = 1) { // get current time DateTime currenttime = DateTime.UtcNow; // convert time to unixtime long currentunixTime = ((DateTimeOffset)currenttime).ToUnixTimeSeconds(); // get 1 hour from current time long minsunixtime = ((DateTimeOffset)currenttime.AddMinutes(exptime)).ToUnixTimeSeconds(); // Get view claims List <Claim> ViewClaim = GetViewClaims(username); // create payload of jwt JwtPayload payload = new JwtPayload() { { "iss", "https://www.Whatfits.social/" }, // { "aud", type }, { "iat", currentunixTime.ToString() }, { "nbf", currentunixTime.ToString() }, { "exp", minsunixtime.ToString() } }; // add username to jwt payload.Add("UserName", username); // add view claims to payload payload.AddClaims(ViewClaim); // return payload return(payload); }
private JwtSecurityToken BuildDeepLinkPostbackToken(JwtSecurityToken requestToken, out string returnUrl) { Claim linkSettings = requestToken.Claims.Single(x => x.Type == LtiClaims.DeepLinkingSettings); JObject settingValues = JObject.Parse(linkSettings.Value); returnUrl = (string)settingValues["deep_link_return_url"]; string data = (string)settingValues["data"]; // first - read tool's private key RSAParameters rsaParams; using (var tr = new StringReader(this.config.ToolPrivateKey)) { var pemReader = new PemReader(tr); var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair; if (keyPair == null) { throw new Exception("Could not read RSA private key"); } var privateRsaParams = keyPair.Private as RsaPrivateCrtKeyParameters; rsaParams = DotNetUtilities.ToRSAParameters(privateRsaParams); } // create security key using private key above var securityKey = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(rsaParams); // note that securityKey length should be >256b so you have to make sure that your private key has a proper length var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.RsaSha256); // create a Token var clientAsssertionJwtTokenHeader = new JwtHeader(signingCredentials); // Some PayLoad that contain information about the caller (tool) // expected payload for access token request.. confirm with IMS guys var now = DateTime.UtcNow; var clientAsssertionJwtTokenPayload = new JwtPayload { { "iss", this.config.ClientId }, //{ "aud", this.config.PlatformTokenEndpoint }, { "aud", requestToken.Issuer }, { "exp", now.AddMinutes(5).Ticks }, // give the user 5 minutes to post the deep link? { "iat", now.Ticks }, { "jti", $"{this.config.ClientId}-{now.Ticks}" }, { "nonce", "377fdbf8cbc2f7b0799b" } }; Claim[] deepLinkResponseClaims = this.BuildResponseClaims(data); clientAsssertionJwtTokenPayload.AddClaims(deepLinkResponseClaims); var clientAsssertionJwtToken = new JwtSecurityToken(clientAsssertionJwtTokenHeader, clientAsssertionJwtTokenPayload); return(clientAsssertionJwtToken); }
public void MatchX5t() { X509SecurityKey signingKey = KeyingMaterial.X509SecurityKeySelfSigned2048_SHA256; X509SecurityKey validateKey = KeyingMaterial.X509SecurityKeySelfSigned2048_SHA256_Public; // Assume SigningKey.KeyId doesn't match validationParameters.IssuerSigningKey.KeyId signingKey.KeyId = null; var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha256Signature); var header = new JwtHeader(signingCredentials); header.Add(JwtHeaderParameterNames.X5t, Base64UrlEncoder.Encode(KeyingMaterial.CertSelfSigned2048_SHA256.GetCertHash())); var payload = new JwtPayload(); payload.AddClaims(ClaimSets.DefaultClaims); var jwtToken = new JwtSecurityToken(header, payload); var handler = new JwtSecurityTokenHandler(); var jwt = handler.WriteToken(jwtToken); var validationParameters = new TokenValidationParameters { RequireExpirationTime = false, RequireSignedTokens = true, ValidateAudience = false, ValidateIssuer = false, ValidateLifetime = false, }; validationParameters.IssuerSigningKey = validateKey; SecurityToken validatedSecurityToken = null; var cp = handler.ValidateToken(jwt, validationParameters, out validatedSecurityToken); validateKey = KeyingMaterial.X509SecurityKeySelfSigned2048_SHA384_Public; validationParameters.IssuerSigningKey = validateKey; ExpectedException expectedException = ExpectedException.SecurityTokenInvalidSignatureException("IDX10503:"); try { cp = handler.ValidateToken(jwt, validationParameters, out validatedSecurityToken); } catch (Exception ex) { expectedException.ProcessException(ex); } }
public void CreateAndValidateTokens_MultipleAudiences() { List <string> errors = new List <string>(); var handler = new JwtSecurityTokenHandler(); var payload = new JwtPayload(); var header = new JwtHeader(); payload.AddClaims(ClaimSets.MultipleAudiences(IdentityUtilities.DefaultIssuer, IdentityUtilities.DefaultIssuer)); var jwtToken = new JwtSecurityToken(header, payload); var jwt = handler.WriteToken(jwtToken); var validationParameters = new TokenValidationParameters { RequireExpirationTime = false, RequireSignedTokens = false, ValidateAudience = false, ValidateIssuer = false, ValidateLifetime = false, }; SecurityToken validatedJwt = null; var cp = handler.ValidateToken(jwt, validationParameters, out validatedJwt); var ci = new ClaimsIdentity(ClaimSets.MultipleAudiences(IdentityUtilities.DefaultIssuer, IdentityUtilities.DefaultIssuer), AuthenticationTypes.Federation); var cpExpected = new ClaimsPrincipal(ci); var compareContext = new CompareContext(); if (!IdentityComparer.AreEqual <ClaimsPrincipal>(cp, cpExpected, compareContext)) { errors.Add("IdentityComparer.AreEqual<ClaimsPrincipal>(cp, cpExpected, compareContext)"); } var audiences = (validatedJwt as JwtSecurityToken).Audiences; var jwtAudiences = jwtToken.Audiences; if (!IdentityComparer.AreEqual <IEnumerable <string> >(audiences, jwtAudiences)) { errors.Add("!IdentityComparer.AreEqual<IEnumerable<string>>(audiences, jwtAudiences)"); } if (!IdentityComparer.AreEqual <IEnumerable <string> >(audiences, IdentityUtilities.DefaultAudiences)) { errors.Add("!IdentityComparer.AreEqual<IEnumerable<string>>(audiences, IdentityUtilities.DefaultAudiences)"); } TestUtilities.AssertFailIfErrors(MethodInfo.GetCurrentMethod().Name, errors); }
private JwtPayload CreateJwtPayload(User user) { var payload = new JwtPayload(); payload.AddClaim(new Claim("email", user.Email, ClaimValueTypes.Email)); payload.AddClaim(new Claim("userId", user.Id.ToString())); payload.AddClaim(new Claim("firstName", user.FirstName)); payload.AddClaim(new Claim("secondName", user.LastName)); payload.AddClaim(new Claim("isConfirmed", user.IsEmailConfirm.ToString(), ClaimValueTypes.Boolean)); payload.AddClaim(new Claim("photoUrl", user.PhotoUrl ?? "")); payload.AddClaim(new Claim("inviteLink", user.InviteLink ?? "")); payload.AddClaims(user.UserRoles.Select(i => new Claim("roles", i.Role.ToString()))); return(payload); }
public JsonWebToken Create(long userId, string email, string fullName, int userType, List <Claim> roleClaims, string profileCode, bool isRegistrationVerified) { var nowUtc = DateTime.UtcNow; var expires = nowUtc.AddMinutes(_options.ExpiryMinutes); var centuryBegins = new DateTime(1970, 1, 1).ToUniversalTime(); var exp = (long)new TimeSpan(expires.Ticks - centuryBegins.Ticks).TotalSeconds; var now = (long)new TimeSpan(nowUtc.Ticks - centuryBegins.Ticks).TotalSeconds; var payload = new JwtPayload { { "sub", userId }, { "iss", _options.Issuer }, { "iat", now }, { "exp", exp }, { "unique_name", email }, { "PolicyCode", profileCode } }; if (roleClaims != null && roleClaims.Count > 0) { payload.AddClaims(roleClaims); } // var claims = new [] // { // new Claim(ClaimTypes) // } var jwt = new JwtSecurityToken(_jwtHeader, payload); var token = _jwtSecurityTokenHandler.WriteToken(jwt); return(new JsonWebToken { Token = token, Expires = exp, // IsRegistrationVerified = isRegistrationVerified ? "Verified" : "Not Verified", // ProfileCode = profileCode, FullName = fullName, UserType = ((UserTypeEnum)userType).GetDescription() }); }
private static JwtPayload CreatePayload(string clientId, string audience, List <Claim>?claims = null) { var payload = new JwtPayload( clientId, audience, null, DateTime.UtcNow, DateTime.UtcNow.AddSeconds(10)); if (claims == null) { return(payload); } var jsonClaims = claims.Where(x => x.ValueType == "json"); var normalClaims = claims.Except(jsonClaims); payload.AddClaims(normalClaims); return(AddJsonToPayload(payload, jsonClaims)); }
public string CreateJwtToken(User user) { _logger.LogDebug("Creating Jwt Token"); var sessionId = Extension.NewGuid().ToString(); //var nowUtc = DateTime.UtcNow; var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); var issueTime = DateTime.UtcNow; var iat = (int)issueTime.Subtract(utc0).TotalSeconds; var exp = (int)issueTime.AddMinutes(_jwtOptions.ExpiryMinutes).Subtract(utc0) .TotalSeconds; var expires = issueTime.AddMinutes(_jwtOptions.ExpiryMinutes); var centuryBegin = new DateTime(1970, 1, 1).ToUniversalTime(); var payload = new JwtPayload { { "sub", user.Username }, { "iss", _jwtOptions.Issuer }, { "iat", iat }, { "exp", exp }, { "unique_name", user.Username } }; //TODO check required claims var claims = new List <Claim> { new Claim(ClaimTypes.Name, user.Username), new Claim(CustomClaimTypes.UserId, $"{user.Username}", "GUID"), //TODO //new Claim(ClaimTypes.Role, user.Role), //TODO new Claim(CustomClaimTypes.SessionId, $"{sessionId}", "GUID"), //TOD TEST }; payload.AddClaims(claims); var jwt = new JwtSecurityToken(_jwtHeader, payload); var token = _jwtSecurityTokenHandler.WriteToken(jwt); return(token); }
public void MultipleX5C() { List <string> errors = new List <string>(); var handler = new JwtSecurityTokenHandler(); var payload = new JwtPayload(); var header = new JwtHeader(); payload.AddClaims(ClaimSets.DefaultClaims); List <string> x5cs = new List <string> { "x5c1", "x5c2" }; header.Add(JwtHeaderParameterNames.X5c, x5cs); var jwtToken = new JwtSecurityToken(header, payload); var jwt = handler.WriteToken(jwtToken); var validationParameters = new TokenValidationParameters { RequireExpirationTime = false, RequireSignedTokens = false, ValidateAudience = false, ValidateIssuer = false, ValidateLifetime = false, }; SecurityToken validatedSecurityToken = null; var cp = handler.ValidateToken(jwt, validationParameters, out validatedSecurityToken); JwtSecurityToken validatedJwt = validatedSecurityToken as JwtSecurityToken; object x5csInHeader = validatedJwt.Header[JwtHeaderParameterNames.X5c]; if (x5csInHeader == null) { errors.Add("1: validatedJwt.Header[JwtHeaderParameterNames.X5c]"); } else { var list = x5csInHeader as IEnumerable <object>; if (list == null) { errors.Add("2: var list = x5csInHeader as IEnumerable<object>; is NULL."); } int num = 0; foreach (var str in list) { var value = str as Newtonsoft.Json.Linq.JValue; if (value != null) { string aud = value.Value as string; if (aud != null) { } } else if (!(str is string)) { errors.Add("3: str is not string, is: " + str.GetType()); errors.Add("token : " + validatedJwt.ToString()); } num++; } if (num != x5cs.Count) { errors.Add("4: num != x5cs.Count. num: " + num.ToString() + "x5cs.Count: " + x5cs.Count.ToString()); } } X509SecurityKey signingKey = KeyingMaterial.X509SecurityKeySelfSigned2048_SHA256; X509SecurityKey validateKey = KeyingMaterial.X509SecurityKeySelfSigned2048_SHA256_Public; // make sure we can still validate with existing logic. var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha256Signature); header = new JwtHeader(signingCredentials); header.Add(JwtHeaderParameterNames.X5c, x5cs); jwtToken = new JwtSecurityToken(header, payload); jwt = handler.WriteToken(jwtToken); validationParameters.IssuerSigningKey = validateKey; validationParameters.RequireSignedTokens = true; validatedSecurityToken = null; cp = handler.ValidateToken(jwt, validationParameters, out validatedSecurityToken); TestUtilities.AssertFailIfErrors("CreateAndValidateTokens_MultipleX5C", errors); }
public static JwtPayload CreateJwtPayload( this Token token, DateTime?creationTime, ILogger logger) { var utcNow = DateTime.UtcNow; var iat = creationTime ?? utcNow; var payload = new JwtPayload( token.Issuer, null, null, utcNow, utcNow.AddSeconds(token.Lifetime), iat); 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 try { foreach (var jClaim in jsonClaims) { // dynamic stuff = JObject.Parse(jClaim.Value); var converter = new ExpandoObjectConverter(); dynamic expando = JsonConvert.DeserializeObject <ExpandoObject>(jClaim.Value, converter); payload.Add(jClaim.Type, expando); } return(payload); } catch (Exception ex) { logger.LogCritical(ex, "Error creating a JSON valued claim"); throw; } }
/// <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()); }
public void CreateAndValidateTokens_MultipleX5C() { List <string> errors = new List <string>(); var handler = new JwtSecurityTokenHandler(); var payload = new JwtPayload(); var header = new JwtHeader(); payload.AddClaims(ClaimSets.MultipleAudiences(IdentityUtilities.DefaultIssuer, IdentityUtilities.DefaultIssuer)); List <string> x5cs = new List <string> { "x5c1", "x5c2" }; header.Add(JwtHeaderParameterNames.X5c, x5cs); var jwtToken = new JwtSecurityToken(header, payload); var jwt = handler.WriteToken(jwtToken); var validationParameters = new TokenValidationParameters { RequireExpirationTime = false, RequireSignedTokens = false, ValidateAudience = false, ValidateIssuer = false, ValidateLifetime = false, }; SecurityToken validatedSecurityToken = null; var cp = handler.ValidateToken(jwt, validationParameters, out validatedSecurityToken); JwtSecurityToken validatedJwt = validatedSecurityToken as JwtSecurityToken; object x5csInHeader = validatedJwt.Header[JwtHeaderParameterNames.X5c]; if (x5csInHeader == null) { errors.Add("1: validatedJwt.Header[JwtHeaderParameterNames.X5c]"); } else { var list = x5csInHeader as IEnumerable <object>; if (list == null) { errors.Add("2: var list = x5csInHeader as IEnumerable<object>; is NULL."); } int num = 0; foreach (var str in list) { num++; if (!(str is string)) { errors.Add("3: str is not string, is:" + str.ToString()); } } if (num != x5cs.Count) { errors.Add("4: num != x5cs.Count. num: " + num.ToString() + "x5cs.Count: " + x5cs.Count.ToString()); } } // make sure we can still validate with existing logic. header = new JwtHeader(KeyingMaterial.DefaultAsymmetricSigningCreds_2048_RsaSha2_Sha2); header.Add(JwtHeaderParameterNames.X5c, x5cs); jwtToken = new JwtSecurityToken(header, payload); jwt = handler.WriteToken(jwtToken); validationParameters.IssuerSigningToken = KeyingMaterial.DefaultAsymmetricX509Token_2048; validationParameters.RequireSignedTokens = true; validatedSecurityToken = null; cp = handler.ValidateToken(jwt, validationParameters, out validatedSecurityToken); TestUtilities.AssertFailIfErrors(MethodInfo.GetCurrentMethod().Name, errors); }
public void CreateAndValidateTokens_MultipleAudiences() { List<string> errors = new List<string>(); var handler = new JwtSecurityTokenHandler(); var payload = new JwtPayload(); var header = new JwtHeader(); payload.AddClaims(ClaimSets.MultipleAudiences(IdentityUtilities.DefaultIssuer, IdentityUtilities.DefaultIssuer)); var jwtToken = new JwtSecurityToken(header, payload); var jwt = handler.WriteToken(jwtToken); var validationParameters = new TokenValidationParameters { RequireExpirationTime = false, RequireSignedTokens = false, ValidateAudience = false, ValidateIssuer = false, ValidateLifetime = false, }; SecurityToken validatedJwt = null; var cp = handler.ValidateToken(jwt, validationParameters, out validatedJwt); var ci = new ClaimsIdentity(ClaimSets.MultipleAudiences(IdentityUtilities.DefaultIssuer, IdentityUtilities.DefaultIssuer), AuthenticationTypes.Federation); var cpExpected = new ClaimsPrincipal(ci); var compareContext = new CompareContext(); if (!IdentityComparer.AreEqual<ClaimsPrincipal>(cp, cpExpected, compareContext)) { errors.Add("IdentityComparer.AreEqual<ClaimsPrincipal>(cp, cpExpected, compareContext)"); } var audiences = (validatedJwt as JwtSecurityToken).Audiences; var jwtAudiences = jwtToken.Audiences; if (!IdentityComparer.AreEqual<IEnumerable<string>>(audiences, jwtAudiences)) { errors.Add("!IdentityComparer.AreEqual<IEnumerable<string>>(audiences, jwtAudiences)"); } if (!IdentityComparer.AreEqual<IEnumerable<string>>(audiences, IdentityUtilities.DefaultAudiences)) { errors.Add("!IdentityComparer.AreEqual<IEnumerable<string>>(audiences, IdentityUtilities.DefaultAudiences)"); } TestUtilities.AssertFailIfErrors(MethodInfo.GetCurrentMethod().Name, errors); }
/// <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; } }