Search code examples
javascriptreactjsgraphqlprismaprisma-graphql

How to generate the JWT token using Prisma API?


I am using prisma to work with the GraphQL. I know there is a way to secure the graphql server with a secret key. For example on specifying the secret key as:

secret: my-secret-42

in prisma.yml , and then running prisma deploy will secure the graphql server and all the subsequent queries will need a JWT token to access it.

I am able to generate the JWT token using the command

prisma token

This gives me the token and on passing it in the headers, I am able to access it. But is there an API using which I could generate the token and I do not have to manually run the prisma token command on the CLI.

I want the javascript to directly access the GraphQL via queries. For this, I need some form of authentication to happen. Since there would be multiple users using the application, I want to have different tokens for different users. Thus I am looking for a way where I could generate the token using the API if available with Prisma.


Solution

  • The service token is a simple JWT token that can easily be created by using service and stage name, as well as the secret. You can create the token yourself and attach it. Take a look at the actual code the prisma CLI is using:

      getToken(serviceName: string, stageName: string): string | undefined {
        if (this.secrets) {
          const data = {
            data: {
              service: `${serviceName}@${stageName}`,
              roles: ['admin'],
            },
          }
          return jwt.sign(data, this.secrets[0], {
            expiresIn: '7d',
          })
        }
    
        return undefined
      }
    

    Source: https://github.com/prisma/prisma/blob/master/cli/packages/prisma-yml/src/PrismaDefinition.ts

    More information regarding the structure:

    Service tokens follow the JSON Web Token (JWT) specification (RFC 7519):

    "JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted."

    A JWT has the following three components:

    Header: The header typically consists of two parts: the type of the token, which is JWT, and the hashing algorithm being used (which is HS256 in the case of Prisma service tokens).

    {   "alg": "HS256",   "typ": "JWT" } 
    

    Payload: The payload contains the claims. Claims are statements about an entity (typically, the user) and additional data. Here is what it looks like for a service called demo deployed to the dev stage:

    {   
       "data": {
          "service": "demo@dev",
          "roles": ["admin"]   
       },   
       "iat": 1532530208,   
       "exp": 1533135008 
    } 
    

    Signature: The signature is used to verify the message wasn't changed along the way. To 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. For example if you want to use the HMAC SHA256 algorithm, the signature will be created in the following way:

    HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret) 
    

    Therefore, a JWT typically looks like this: xxxxx.yyyyy.zzzzz

    Source: https://www.prisma.io/docs/prisma-server/authentication-and-security-kke4/#service-token