Reputation: 303
Could anyone provide me an example for generating jwt tokens with three headers given as (alg, kid, typ) that has the format:
{
"alg": "RS256",
"kid": "vpaas-magic-cookie-1fc542a3e4414a44b2611668195e2bfe/4f4910",
"typ": "JWT"
}
under https://developer.8x8.com/jaas/docs/api-keys-jwt.
Jwt tokens get expired with a time limit of few hours so I am trying to find a way to generate the token in my code itself.
At the end, my javascript looks like this, where I add the jwt token inside the options list for authentication.
var options = {
roomName: "vpaas-magic-cookie-secretKey/Room123",
jwt: 'JWTTOKEN',
,
From what I have read under https://jwt.io/, I need the encoded key from the decoded details. As per the generating tokens, I think it uses HS256 algorithm. What are the steps to do this in javascript?
EDIT: After the user's answer, I did some changes to his code and I am currently generating half the JWT token. I am checking it with the already generated token on the server - Jaas.8x8
<script>
const HMACSHA256 = (stringToSign, secret) => "not_implemented"
// The header typically consists of two parts:
// the type of the token, which is JWT, and the signing algorithm being used,
// such as HMAC SHA256 or RSA.
const header = {
"kid": "vpaas-magic-cookie-07fabede3674457a84c95fsecretcode/myroom001",
"alg": "RS256",
"typ": "JWT"
}
const encodedHeaders = btoa(JSON.stringify(header))
// create the signature part you have to take the encoded header,
// the encoded payload, a secret, the algorithm specified in the header,
// and sign that.
const signature = HMACSHA256(`${encodedHeaders}`, "mysecret")
console.log(`${encodedHeaders}.${signature}`)
</script>
The token that gets generated from code is
eyJraWQiOiJ2cGFhcy1tYWdpYy1jb29raWUtMDdmYWJlZGUzNjc0NDU3YTg0Yzk1ZmE4MGIxNGY1ZDcvVGVzdFJhdW0wMDEiLCJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.not_implemented
And the token that is already generated online is:
eyJraWQiOiJ2cGFhcy1tYWdpYy1jb29raWUtMDdmYWJlZGUzNjc0NDU3YTg0Yzk1ZmE4MGIxNGY1ZDcvMTg1ZDY2LVNBTVBMRV9BUFAiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJqaXRzaSIsImV4cCI6MTYyMDM4ODU3NiwibmJmIjoxNjIwMzgxMzcxLCJpc3MiOiJjaGF0Iiwicm9vbSI6IioiLCJzdWIiOiJ2cGFhcy1tYWdpYy1jb29raWUtMDdmYWJlZGUzNjc0NDU3YTg0Yzk1ZmE4MGIxNGY1ZDciLCJjb250ZXh0Ijp7ImZlYXR1cmVzIjp7ImxpdmVzdHJlYW1pbmciOmZhbHNlLCJvdXRib3VuZC1jYWxsIjpmYWxzZSwidHJhbnNjcmlwdGlvbiI6ZmFsc2UsInJlY29yZGluZyI6ZmFsc2V9LCJ1c2VyIjp7Im1vZGVyYXRvciI6dHJ1ZSwibmFtZSI6IlRlc3QgVXNlciIsImlkIjoiYXV0aDB8NjA5M2EyYzM3Zjc3MGEwMDcxMGE5YzY5IiwiYXZhdGFyIjoiIiwiZW1haWwiOiJ0ZXN0LnVzZXJAY29tcGFueS5jb20ifX19.aNqg_VLXyafH8Se5rThe6TLz0F2AEnJSmuoZBQ4fXEm1PMx4SBRpelJsrmL76D_jKS5NT-GkuPDVcDgLv6nx9G4ywjws1AH4Lkt0FcJ3eH2OjbFI2WxPzJF_tDJbtPme5LJmGZwEa509v2QD0r-kr31M7FZ83S-kz3O1xKc33FnMJwNlqvgCSN2S0QwF6R5J01zDk41gCk0wGr3DXAmlz0FtCU0qJ5nN9iMUpr5QUY1D-hRApWMhoLPmxkuqnQKLjGwgxU8lh33wq_Laqu7qV57lYrI27er_c42YePwuitWEAAshQU4Ylf2v8sVRv06kQdFPVvICVdsTTI-DLbc3aQ
So basically the first few strings are right but the rest is not generated. I assume it has something to do with mysecret? What exactly is this?
Upvotes: 13
Views: 46646
Reputation: 20547
All the instructions are written on this page, https://jwt.io/introduction.
For simplicity, I did not implement HMACSHA256 or use a library to do it. You need to implement this function.
const HMACSHA256 = (stringToSign, secret) => "not_implemented"
// The header typically consists of two parts:
// the type of the token, which is JWT, and the signing algorithm being used,
// such as HMAC SHA256 or RSA.
const header = {
"alg": "HS256",
"typ": "JWT"
}
const encodedHeaders = btoa(JSON.stringify(header))
// The second part of the token is the payload, which contains the claims.
// Claims are statements about an entity (typically, the user) and
// additional data. There are three types of claims:
// registered, public, and private claims.
const claims = {
"role": "admin"
}
const encodedPayload = btoa(JSON.stringify(claims))
// create the signature part you have to take the encoded header,
// the encoded payload, a secret, the algorithm specified in the header,
// and sign that.
const signature = HMACSHA256(`${encodedHeaders}.${encodedPayload}`, "mysecret")
const encodedSignature = btoa(signature)
const jwt = `${encodedHeaders}.${encodedPayload}.${encodedSignature}`
console.log({jwt})
Note, that my answer differs from your question in that it is using HS256 instead of RS256. If you want to learn more about the difference you can take a look here: RS256 vs HS256: What's the difference?.
Upvotes: 18
Reputation: 1450
function base64url(source) {
let encodedSource = CryptoJS.enc.Base64.stringify(source);
encodedSource = encodedSource.replace(/=+$/, '');
encodedSource = encodedSource.replace(/\+/g, '-');
encodedSource = encodedSource.replace(/\//g, '_');
return encodedSource;
}
function jwtSign(payload, secretOrPrivateKey) {
const header = { 'alg': 'HS256', 'typ': 'JWT' };
const stringifiedHeader = CryptoJS.enc.Utf8.parse(JSON.stringify(header));
const encodedHeader = base64url(stringifiedHeader);
const stringifiedPayload = CryptoJS.enc.Utf8.parse(JSON.stringify(payload));
const encodedPayload = base64url(stringifiedPayload);
const encodedSignature = base64url(CryptoJS.HmacSHA256(encodedHeader + "." + encodedPayload, secretOrPrivateKey));
return encodedHeader + "." + encodedPayload + "." + encodedSignature;
}
const token = jwtSign({ 'field1': 'test1', 'fileId2': 'test2'}, 'test key');
console.log(token);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js"></script>
The above code snippets are working.
Upvotes: 0