Signing a JSON Web Token in Erlang
About 8 years ago, I wrote a post about verifying JSON Web Tokens (JWT) in Erlang. 3 years later, I wrote another post about signing a JWT in bash. This is a post combining the two: here’s how you sign a JWT using Erlang.
A JWT needs a header, which is base64url-encoded:
Header = base64url:encode(
jsx:encode(
#{<<"alg">> => <<"RS256">>,
<<"typ">> => <<"JWT">>}
)).
Then you need a payload with some claims; the list of required vs. optional claims depends on the particular
implementation. I’ll use the initial list from the jwt.io
debugger.
This is also base64url-encoded.
Payload = base64url:encode(
jsx:encode(
#{<<"sub">> => <<"1234567890">>,
<<"name">> => <<"John Doe">>,
<<"iat">> => 1516239022}
)).
The iat
(issued at) value is from 2018, in case you were wondering, per date --date=@1516239022
.
We then combine the two:
Message = <<Header/binary, ".", Payload/binary>>.
The RS256
algorithm requires an RSA key, so we’ll need to generate one:
SigningKey = public_key:generate_key({rsa, 2048, 65537}).
And then we can sign the token, which needs to be base64url-encoded again:
Signature = base64url:encode(
public_key:sign(Message, sha256, SigningKey)).
We append that to the header and payload, and we’ve got our final JSON Web Token:
JWT = <<Header/binary, ".", Payload/binary, ".", Signature/binary>>.