1

I'm trying to construct a JWT token manually by building the three components and then combining them. According to this: https://jwt.io/ there are three parts to this token; a JWT header, a payload and a signature. The follwoing code seems to successfully generate the first two. but the signature is not correct :

public async Task<string> GetJWTToken(string user) { var now = DateTime.UtcNow; //constructing part 1: header.Encode() JwtHeader jwtHeader = new JwtHeader(); jwtHeader.Add("alg", JwtAlgorithms.HMAC_SHA512); var partOne = jwtHeader.Base64UrlEncode(); //constructing part 2: payload.Encode JwtPayload payload = new JwtPayload(); payload.Add("sub", user); payload.Add("nbf",ConvertToUnixTimestamp(now.AddMinutes(-10))); var partTwo = payload.Base64UrlEncode(); //constructing part 3: HS512(part1 + "." + part2, key) var tobeHashed = partOne + "." + partTwo; var sha = new HMACSHA512(Encoding.UTF8.GetBytes(ConfigurationHelper.AppSettings("JWTOfferKey"))); var hashedByteArray = sha.ComputeHash(Encoding.UTF8.GetBytes(tobeHashed)); StringBuilder partThree = new StringBuilder(); foreach (var hashedByte in hashedByteArray) { partThree.Append(hashedByte.ToString("X2")); } //token = part1 + "." + part2 + "." + part3 var tokenString = partOne + "." + partTwo + "." + Base64Encode(partThree.ToString()); return tokenString; } public static double ConvertToUnixTimestamp(DateTime date) { DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); TimeSpan diff = date.ToUniversalTime() - origin; return Math.Floor(diff.TotalSeconds); } public static string Base64Encode(string plainText) { var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); return System.Convert.ToBase64String(plainTextBytes); } 

Does anyone know what is wrong with the last part's construction?

1 Answer 1

2

What is wrong with the last part's construction?

You need to base64UrlEncode the signature hash value

public Task<string> GetJWTToken(string user) { //...other code removed for brevity //constructing part 3: HS512(part1 + "." + part2, key) var tobeHashed = string.Join(".", partOne, partTwo); var sha = new HMACSHA512(Encoding.UTF8.GetBytes(ConfigurationHelper.AppSettings("JWTOfferKey"))); var hashedByteArray = sha.ComputeHash(Encoding.UTF8.GetBytes(tobeHashed)); //You need to base64UrlEncode the signature hash value var partThree = Base64UrlEncode(hashedByteArray); //Now construct the token var tokenString = string.Join(".", tobeHashed, partThree); //await was not used so no need for `async` keyword. Just return task return Task.FromResult(tokenString); } // from JWT spec private static string Base64UrlEncode(byte[] input) { var output = Convert.ToBase64String(input); output = output.Split('=')[0]; // Remove any trailing '='s output = output.Replace('+', '-'); // 62nd char of encoding output = output.Replace('/', '_'); // 63rd char of encoding return output; } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.