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?
1 Answer
$\begingroup$ $\endgroup$
2 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" *) - 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) useDeveloper`EncodeBase64[...]instead ofExportString[..., "Base64"]to suppress newlines in the token. $\endgroup$WReach– WReach2020-06-17 02:27:52 +00:00Commented Jun 17, 2020 at 2:27 - $\begingroup$ Wonderful! Thank you so much for your answer. $\endgroup$Andy Burnett– Andy Burnett2020-06-17 16:04:41 +00:00Commented Jun 17, 2020 at 16:04