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);
        }
Beispiel #2
0
        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
            });
        }
Beispiel #3
0
        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));
        }
Beispiel #4
0
        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)));
        }
Beispiel #5
0
        /// <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);
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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);
        }
Beispiel #10
0
        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()
            });
        }
Beispiel #11
0
        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));
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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);
        }
Beispiel #14
0
        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));
        }
Beispiel #17
0
        /// <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);
        }
Beispiel #20
0
        /// <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;
            }
        }