/// <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); } }
/// <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); } }