예제 #1
0
        /// <summary>
        /// Gets the access token of an user that associate with a session and return a JSON Web Token
        /// </summary>
        /// <param name="userID">The string that presents the identity of the user</param>
        /// <param name="sessionID">The string that presents the identity of the associated session</param>
        /// <param name="roles">The collection that presents the roles that the user was belong to</param>
        /// <param name="privileges">The collection that presents the access privileges that the user was got</param>
        /// <param name="key">The key used to encrypt and sign</param>
        /// <param name="onCompleted">The action to run to modify playload (if needed) when the processing is completed</param>
        /// <param name="hashAlgorithm">The hash algorithm used to hash and sign (md5, sha1, sha256, sha384, sha512, ripemd/ripemd160, blake128, blake/blake256, blake384, blake512)</param>
        /// <returns>A JSON Web Token that presents the access token</returns>
        public static string GetAccessToken(string userID, string sessionID, IEnumerable <string> roles, IEnumerable <Privilege> privileges, BigInteger key, Action <JObject> onCompleted = null, string hashAlgorithm = "BLAKE256")
        {
            var token = new JObject
            {
                { "jti", sessionID },
                { "uid", userID },
                { "rls", (roles ?? new List <string>()).Distinct(StringComparer.OrdinalIgnoreCase).ToJArray() },
                { "pls", (privileges ?? new List <Privilege>()).ToJArray() }
            }.ToString(Formatting.None);
            var hash      = token.GetHash(hashAlgorithm);
            var signature = key.Sign(hash);
            var publicKey = key.GenerateECCPublicKey();
            var payload   = new JObject
            {
                { "iat", DateTime.Now.ToUnixTimestamp() },
                { "exp", DateTime.Now.AddDays(90).ToUnixTimestamp() },
                { "nbf", DateTime.Now.AddDays(-30).ToUnixTimestamp() },
                { "jti", publicKey.Encrypt(sessionID.HexToBytes()).ToHex() },
                { "uid", userID },
                { "atk", publicKey.Encrypt(token, true) },
                { "ath", hash.ToHex() },
                { "sig", ECCsecp256k1.GetSignature(signature) }
            };

            onCompleted?.Invoke(payload);
            return(JSONWebToken.Encode(payload, ECCsecp256k1.GetPublicKey(publicKey).ToHex(), hashAlgorithm));
        }
예제 #2
0
        /// <summary>
        /// Parses the given authenticate token and return an <see cref="User">UserIdentity</see> object
        /// </summary>
        /// <param name="authenticateToken">The JSON Web Token that presents the authenticate token</param>
        /// <param name="encryptionKey">The passphrase that used to generate the encryption key for decrypting data using AES</param>
        /// <param name="signKey">The passphrase that used to sign and verify the token</param>
        /// <param name="expiredAfter">The seconds that the token is expired (default is 60 seconds) </param>
        /// <param name="onCompleted">The action to run when  the processing is completed</param>
        /// <returns>The <see cref="User">UserIdentity</see> object that presented by the authenticate token</returns>
        public static User ParseAuthenticateToken(this string authenticateToken, string encryptionKey, string signKey, int expiredAfter = 0, Action <JObject, User> onCompleted = null)
        {
            try
            {
                // decode JSON Web Token
                var payload = JSONWebToken.DecodeAsJson(authenticateToken, signKey);
                var token   = payload.ToExpandoObject();

                // issued at (expired after XXX seconds)
                var issuedAt = token.Get <long>("iat");
                if (DateTime.Now.ToUnixTimestamp() - issuedAt > (expiredAfter > 0 ? expiredAfter : 60))
                {
                    throw new TokenExpiredException();
                }

                // identities
                var tokenID    = token.Get <string>("jti");
                var userID     = token.Get <string>("uid");
                var audienceID = token.Get <string>("aud");
                var sessionID  = token.Get <string>("sid");

                if (string.IsNullOrWhiteSpace(tokenID) || string.IsNullOrWhiteSpace(sessionID) || string.IsNullOrWhiteSpace(audienceID) || userID == null)
                {
                    throw new InvalidTokenException("Invalid identity");
                }

                sessionID = sessionID.HexToBytes().Decrypt(encryptionKey.GenerateHashKey(256), encryptionKey.GenerateHashKey(128)).ToHex();
                if (!tokenID.Equals($"{userID}@{sessionID}".GetHMACBLAKE256(encryptionKey)))
                {
                    throw new InvalidTokenException("Invalid identity");
                }

                if (userID.Equals("") && !audienceID.Equals(UtilityService.BlankUUID.GetHMACBLAKE128(signKey)))
                {
                    throw new InvalidTokenException("Invalid identity");
                }
                else if (!userID.Equals("") && !audienceID.Equals(userID.GetHMACBLAKE128(signKey)))
                {
                    throw new InvalidTokenException("Invalid identity");
                }

                // create user identity
                var user = new User(userID, sessionID, null, null);

                // callback
                onCompleted?.Invoke(payload, user);

                // return user identity
                return(user);
            }
            catch (Exception ex)
            {
                if (ex is TokenExpiredException || ex is InvalidTokenSignatureException || ex is InvalidTokenException)
                {
                    throw;
                }
                throw new InvalidTokenException("Invalid authenticate token", ex);
            }
        }
예제 #3
0
        /// <summary>
        /// Gets the authenticate token of an user that associate with a session and return a JSON Web Token
        /// </summary>
        /// <param name="userID">The string that presents identity of an user</param>
        /// <param name="sessionID">The string that presents identity of working session that associated with user</param>
        /// <param name="encryptionKey">The passphrase that used to encrypt data using AES</param>
        /// <param name="signKey">The passphrase that used to sign the token</param>
        /// <param name="onCompleted">The action to run when the processing is completed</param>
        /// <returns>A JSON Web Token that presents the authenticate token</returns>
        public static string GetAuthenticateToken(string userID, string sessionID, string encryptionKey, string signKey, Action <JObject> onCompleted = null)
        {
            var payload = new JObject
            {
                { "iat", DateTime.Now.ToUnixTimestamp() },
                { "jti", $"{userID}@{sessionID}".GetHMACBLAKE256(encryptionKey) },
                { "sid", sessionID.HexToBytes().Encrypt(encryptionKey.GenerateHashKey(256), encryptionKey.GenerateHashKey(128)).ToHex() },
                { "aud", (string.IsNullOrWhiteSpace(userID) ? UtilityService.BlankUUID : userID).GetHMACBLAKE128(signKey) },
                { "uid", userID }
            };

            onCompleted?.Invoke(payload);
            return(JSONWebToken.Encode(payload, signKey));
        }
예제 #4
0
        /// <summary>
        /// Parses the given access token and return an <see cref="User">User</see> object
        /// </summary>
        /// <param name="accessToken">The JSON Web Token that presents the access token</param>
        /// <param name="key">The key used to decrypt and verify</param>
        /// <param name="onCompleted">The action to run to update user information (if needed) when the processing is completed</param>
        /// <param name="hashAlgorithm">The hash algorithm used to hash and sign (md5, sha1, sha256, sha384, sha512, ripemd/ripemd160, blake128, blake/blake256, blake384, blake512)</param>
        /// <returns>The <see cref="User">User</see> object that presented by the access token</returns>
        public static User ParseAccessToken(this string accessToken, BigInteger key, Action <JObject, User> onCompleted = null, string hashAlgorithm = "BLAKE256")
        {
            try
            {
                // decode JSON Web Token
                var publicKey = key.GenerateECCPublicKey();
                var payload   = JSONWebToken.DecodeAsJson(accessToken, ECCsecp256k1.GetPublicKey(publicKey).ToHex());
                var token     = payload.ToExpandoObject();

                // times
                var issuedAt  = token.Get <long>("iat").FromUnixTimestamp();
                var expiresAt = token.Get <long>("exp").FromUnixTimestamp();
                var notBefore = token.Get <long>("nbf").FromUnixTimestamp();
                if (DateTime.Now > expiresAt || DateTime.Now < notBefore || issuedAt > expiresAt || issuedAt < notBefore)
                {
                    throw new TokenExpiredException();
                }

                // identities
                var tokenID = token.Get <string>("jti");
                var userID  = token.Get <string>("uid");
                if (string.IsNullOrWhiteSpace(tokenID) || string.IsNullOrWhiteSpace(userID))
                {
                    throw new InvalidTokenException("Invalid identity");
                }
                else
                {
                    tokenID = key.Decrypt(tokenID.HexToBytes()).ToHex();
                }

                // signature
                var hash      = token.Get <string>("ath").HexToBytes();
                var signature = ECCsecp256k1.GetSignature(token.Get <string>("sig"));
                if (!publicKey.Verify(hash, signature))
                {
                    throw new InvalidTokenSignatureException();
                }

                accessToken = key.Decrypt(token.Get <string>("atk"), true);
                if (!hash.SequenceEqual(accessToken.GetHash(hashAlgorithm)))
                {
                    throw new InvalidTokenException("Not matched");
                }

                // info of access token
                token = accessToken.ToExpandoObject();
                if (!userID.IsEquals(token.Get <string>("uid")) || !tokenID.IsEquals(token.Get <string>("jti")))
                {
                    throw new InvalidTokenException("Invalid identity");
                }

                var roles      = token.Get <List <string> >("rls");
                var privileges = token.Get <List <Privilege> >("pls");

                // create new user identity
                var user = new User(userID, tokenID, roles, privileges);

                // callback
                onCompleted?.Invoke(payload, user);

                // return user identity
                return(user);
            }
            catch (Exception ex)
            {
                if (ex is TokenExpiredException || ex is InvalidTokenSignatureException || ex is InvalidTokenException)
                {
                    throw;
                }
                throw new InvalidTokenException("Invalid access token", ex);
            }
        }
예제 #5
0
 /// <summary>
 /// Decodes a given JSON Web Token and return the JSON payload
 /// </summary>
 /// <param name="token">The JSON Web Token</param>
 /// <param name="key">The key that were used to sign the JSON Web Token</param>
 /// <param name="verify">Whether to verify the signature</param>
 /// <returns>An <see cref="JObject">JObject</see> object that representing the payload</returns>
 /// <exception cref="InvalidTokenSignatureException">Thrown if the verify parameter was true and the signature was NOT valid or if the JWT was signed with an unsupported algorithm</exception>
 public static JObject DecodeAsJson(string token, string key, bool verify = true)
 => JObject.Parse(JSONWebToken.Decode(token, key, verify));