6
$\begingroup$

I want to access a service that uses JWT authentication for its API. Generating a JWT doesn't look too difficult, it is a combination of BASE64URL encoding, and HMAC Signing. However, these things can be a finicky to get right, so I was wondering if anyone had done this in Mathematica? For instance, is it possible to use the SecuredAuthenticationKey function to do what I need?

$\endgroup$

1 Answer 1

6
$\begingroup$

I stole the HMAC from here https://mathematica.stackexchange.com/a/167636/72682. The header/payload/secret are the same as the ones on the Wikipedia page https://en.wikipedia.org/wiki/JSON_Web_Token. Thanks to the suggestions in @WReach's comment I was able to get the same token in the Wikipedia article.

hmacFnew[method_, message_, key_] := 
 Module[{dkey, dmsg, opad, ipad, blocksize}, 
  blocksize = If[method === "SHA384" || method === "SHA512", 128, 64];
  {dkey, dmsg} = StringToByteArray /@ {key, message};
  If[Length[dkey] > blocksize, dkey = Hash[dkey, method, "ByteArray"]];
  dkey = Normal[dkey];
  If[Length[dkey] < blocksize, dkey = PadRight[dkey, blocksize, 0]];
  {opad, ipad} = ByteArray[BitXor[dkey, ConstantArray[#, blocksize]]] & /@ {92, 54};
  Hash[Join[opad, Hash[Join[ipad, dmsg], method, "ByteArray"]], method, "Base64Encoding"]]

urlfixb64[b64_?StringQ] := 
 StringReplace[StringSplit[b64, "="][[1]], {"+" -> "-", "/" -> "_"}]

secret = "secretkey";
header = <|"alg" -> "HS256", "typ" -> "JWT"|>;
payload = <|"loggedInAs" -> "admin", "iat" -> 1422779638|>;
headerJSON = ExportString[header, "JSON", "Compact" -> True];
payloadJSON = ExportString[payload, "JSON", "Compact" -> True];
header64 = Developer`EncodeBase64[headerJSON] // urlfixb64;
payload64 = Developer`EncodeBase64[payloadJSON] // urlfixb64;
signature = hmacFnew["SHA256", header64 ~~ "." ~~ payload64, secret] // urlfixb64;
token = header64 ~~ "." ~~ payload64 ~~ "." ~~ signature

(* result: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dnZWRJbkFzIjoiYWRtaW4iLCJpYXQiOjE0MjI3Nzk2Mzh9.gzSraSYS8EXBxLN_oWnFSRgCzcmJmMjLiuyu5CSpyHI" *)
$\endgroup$
2
  • 2
    $\begingroup$ +1. You can get the exact result from the Wikipedia article if you: 1) use ExportString[..., "JSON", "Compact"->True] to suppress pretty-printing and 2) use Developer`EncodeBase64[...] instead of ExportString[..., "Base64"] to suppress newlines in the token. $\endgroup$ Commented Jun 17, 2020 at 2:27
  • $\begingroup$ Wonderful! Thank you so much for your answer. $\endgroup$ Commented Jun 17, 2020 at 16:04

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.