Please review my code for 'JWT' authentication.

  1. Are there any security issues?
  2. Where should I store the secret's key, DB or InMemory?
  3. What's a good 'JWT' Lifetime?
  4. Should I send the 'JWT' in Header for every request?
  5. What should be done when a 'JWT' Expires?

Token Manager

using System;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;
using Procoor_V4_Model.SecurityModel;

namespace Procoor_V4_Security
    public class TokenManager
        public static string EncodeToken(JwtPayload jwtPayload, string secret)
            const string algorithm = "HS256";

            var header = new JwtHeader
                Typ = "JWT", 
                Alg = algorithm

            var jwt = Base64Encode(JsonConvert.SerializeObject(header)) + "." + Base64Encode(JsonConvert.SerializeObject(jwtPayload));

            jwt += "." + Sign(jwt, secret);

            return jwt;

        public static JwtPayload DecodeToken(string token, string secret)
            var segments = token.Split('.');

            if(segments.Length != 3)
                throw new Exception("Token structure is incorrect!");

            JwtHeader header = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(Base64Decode(segments[0])), typeof(JwtHeader));
            JwtPayload jwtPayload = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(Base64Decode(segments[1])), typeof(JwtPayload));

            var rawSignature = segments[0] + '.' + segments[1];

            if(!Verify(rawSignature, secret, segments[2]))
                throw new Exception("Verification Failed");

            return jwtPayload;

        private static bool Verify(string rawSignature, string secret, string signature)
            return signature == Sign(rawSignature, secret);

        private static string Sign(string str, string key)
            var encoding = new ASCIIEncoding();

            byte[] signature;

            using (var crypto = new HMACSHA256(encoding.GetBytes(key)))
                signature = crypto.ComputeHash(encoding.GetBytes(str));

            return Base64Encode(signature);

        public static string Base64Encode(dynamic obj)
            Type strType = obj.GetType();

            var base64EncodedValue = Convert.ToBase64String(strType.Name.ToLower() == "string" ? Encoding.UTF8.GetBytes(obj) : obj);

            return base64EncodedValue;

        public static dynamic Base64Decode(string str)
            var base64DecodedValue = Convert.FromBase64String(str);

            return base64DecodedValue;

How I currently use it:

var secret = TokenManager.Base64Encode(SecurityConstants.KeyForHmacSha256);
var currentTime = (long)(DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime()).TotalSeconds;
var payload = new JwtPayload
    iss = SecurityConstants.TokenIssuer,
    sub = "46897484",
    iat = currentTime,
    exp = currentTime + 1800

var jwt = TokenManager.CreateJwtToken(payload, secret);
  • \$\begingroup\$ I see that you are verifying the signature by creating your own signature and comparing it with the one you want to verify. This doesn't seem right to me as you need the secret key to do it. You shouldn't need the secret key to verify a signature, surely? \$\endgroup\$ Aug 10, 2017 at 10:47
  • \$\begingroup\$ Hey I was trying to use your code. But I get an error for the Type = "JWT" part. it says JwtHeader.Typ can not be assigned to its read only. Why are you able to assign a value if its read only. Thanks. \$\endgroup\$ Dec 18, 2020 at 20:17
  • \$\begingroup\$ @TakafuKeyomama Sorry mate, This code is outdated and haven't been maintained for a while now. \$\endgroup\$ Dec 19, 2020 at 20:59

1 Answer 1


Are there any security issues? Where should I store the secret's key, DB or InMemory? What's a good 'JWT' Lifetime? Should I send the 'JWT' in Header for every request? What should be done when a 'JWT' Expires?

  1. The contents are merely base64 encoded and thus are simple to decode -- so don't encode your valued customers personal data.

cut and paste your token in here as evidence https://developers.google.com/wallet/digital/docs/jwtdecoder

  1. the secret key is not a session one so in memory makes no sense. buy an oracle license and then stick it in there. or theres nothing wrong with something nice and simple like this.

        const string algorithm = "HS256";
  2. if you're logging a user onto a site. 1 hour? its possible to copy/paste the token and gain access to data. so it depends on the nature of the data.

  3. yes. its an awesome method to send to a REST server instead of some internal userid that never expires

  4. kick them out of your site. make them relog in and get a new token (with another hour long token)

  • \$\begingroup\$ Thanks for your answer, I just wanted to make sure of something, The key should be a constant and not changed with every time a 'JWT' expires? \$\endgroup\$ Nov 17, 2014 at 7:39
  • 1
    \$\begingroup\$ correct. the key is constant. \$\endgroup\$ Nov 17, 2014 at 8:07
  • \$\begingroup\$ One more question if you may be patient, I am very grateful for your time, The Secret Key if same for all users not just one, and now that i know it's a constant do i have to change it over a period of time. \$\endgroup\$ Nov 17, 2014 at 8:21
  • \$\begingroup\$ Sorry friend. Back to work. The secret key you receive from Facebook, Live or other OAuth provider is the same one used for all users. Its not a classic password situation. Its used to sign the contents of the JWT. Therefore, when the content (including username of user) of the JWT changes, so does the resulting hashed signature. That hash is added and sent WITH the token. The secret key is used to decode the signature and thereby verifying the JWT and its contents (are constructed by provider you expect). You will see evidence of the hash in that google decoder. The hash is labeled signature \$\endgroup\$ Dec 2, 2014 at 22:46
  • \$\begingroup\$ @GabeRainbow: "The secret key is used to decode the signature" -> that's false, the secret is used to apply the stated hash-crypt algorithm to the readable header and body of the JWT and the JWT will be considered valid if the generated signature matches the one provided in the JWT. Only encryption is used, no decryption. \$\endgroup\$
    – klaar
    Jan 13, 2017 at 10:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.