Generating JWT tokens
Asked Answered
S

2

13

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?

JWT Token

Seduce answered 7/5, 2021 at 9:11 Comment(5)
"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." If you just need a longer lived token, you might consider adjusting the expiration timing on the token rather than reinventing the wheel here.Avantgarde
@HenryEcker thank you for your reply. I want to do that but the api-keys where I get my JWT token has a maximum limit of only 2 hours.Seduce
are you looking to do it with plain javascript or do you want a token by any means?Periphrastic
@TheFool I am trying to do it with plain js, I came across base64 header in javascript. Maybe that is the key to do this?Seduce
The header that you posted at the beginning of your question comes from a token signed with an asymmetric algorithm. To create such token you would need to have access to the Authorization Server's private certificate, which is used to sign tokens. The thing you're trying to do just doesn't seem right - you can't issue tokens in your code and expect them to work as tokens issued by some different Authorization Server. Unless you own the private keys of the server, only then you can mimic that behaviour.Abound
P
17

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?.

Periphrastic answered 7/5, 2021 at 9:40 Comment(4)
jose is JavaScript module for JSON Object Signing and Encryption, providing support for JSON Web Tokens (JWT)Lavalava
For Typescript I had to use window.btoa, but otherwise this was a good solution for creating test JWT tokens that just needed to be syntactically valid.Hunyadi
@DrewReese, be careful as btoa is not url safe. If you want to be really correct you need to create your own url safe base64 as there is none in the browser afaik. Btoa will work sometimes but its really just flipping the coin.Periphrastic
Thanks for the heads up. That's probably fine for my use case, Storybook with MSW addon where we've some components with react-query hooks that check for a stored token prior to making requests. I just needed a token for testing to get to the query code that is hijacked with mock responses. If we needed anything more substantial I'd probably just integrate jwt-encode.Hunyadi
H
0

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.

Heartbreaking answered 15/4 at 0:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.