claims key: 'https://hasura.io/jwt/claims' not found

52 Views Asked by At

I am trying to implement AWS Cognito authentication in a web app (Angular, Node JS, Serverless) that uses hasura graphql APIs for CRUD operations and am following this article for reference. I have setup a user pool, created an app client, created a lambda function to add jwt_claims and also added a pre token generation trigger for the lambda function exactly as mentioned in the article.

In the JS app I am using amazon-cognito-identity-js library to authenticate my users as follows:

  login(username: string, password: string): Promise<any> {
    let _this = this;
    let promise = new Promise((resolve, reject) => {
      const authenticationData = {
        Username: username,
        Password: password,
      };
      const authenticationDetails = new AuthenticationDetails(authenticationData);
      const poolData = {
        UserPoolId: this.UserPoolId,
        ClientId: this.ClientId,
      };
      const userPool = new CognitoUserPool(poolData);
      const userData = {
        Username: username,
        Pool: userPool,
      };
      const cognitoUser = new CognitoUser(userData);
      cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: function(result) {
          const token = {
            access_token: result.getAccessToken().getJwtToken(),
            id_token: result.getIdToken().getJwtToken(),
            refresh_token: result.getRefreshToken().getToken(),
          };
          _this.setCredentials(token, true);
          _this.router.navigate(['dashboard']);
          return of(result);
        },
        onFailure: function(err) {
          return resolve(err);
        },
        newPasswordRequired: function(userAttributes, requiredAttributes) {
          console.log(userAttributes);
          console.log(requiredAttributes);
          let newPassword = prompt('Please enter a new password: ', '') || '';
          cognitoUser.completeNewPasswordChallenge(newPassword, {}, this);
        }
      });
    });
    return promise;
  }

But When the above method is called and an authentication request is sent to cognito, the AWS lambda function errors out with the following output.

{"__type":"UserLambdaValidationException","message":"PreTokenGeneration failed with error exports is not defined in ES module scope."}

I have tried updating the lambda function from

exports.handler = (event, context, callback) => {
  event.response = {
    claimsOverrideDetails: {
      claimsToAddOrOverride: {
        "https://hasura.io/jwt/claims": JSON.stringify({
          "x-hasura-user-id": event.request.userAttributes.sub,
          "x-hasura-default-role": "user",
          "x-hasura-allowed-roles": ["user"],
        }),
      },
    },
  };
  callback(null, event);
};

to

export const handler = (event, context, callback) => {
  event.response = {
    claimsOverrideDetails: {
      claimsToAddOrOverride: {
        "https://hasura.io/jwt/claims": JSON.stringify({
          "x-hasura-user-id": event.request.userAttributes.sub,
          "x-hasura-default-role": "user",
          "x-hasura-allowed-roles": ["user"],
        }),
      },
    },
  };
  callback(null, event);
};

and cognito returns the access_token, id_token & refresh_token as expected but seems like the claim data is not being added to the response for some reason as when I use the access_token I received from cognito after authentication in the Authorization header to access data via hasura graphql API, Hasura gives me the following error:

{
  "errors": [
    {
      "message": "claims key: 'https://hasura.io/jwt/claims' not found",
      "extensions": {
        "path": "$",
        "code": "jwt-invalid-claims"
      }
    }
  ]
}

I do not understand what I am doing wrong here. This has already taken more time than expected for me and hence I am looking out for some help. I would really appreciate any directions, suggestions or solutions to this.

(Update: Added More Information below)

Just to add some more hasura config information, I have also added the HASURA_GRAPHQL_JWT_SECRET environment variable to hasura.

NOTE: I have replaced my actual user pool id from the code below for security purposes and replaced it with <user_pool_id>. In the congifguration on hasura end the jwk_url contains the actual user pool id and I am also able to view the public key information when I visit the jwk_url

It looks like this:

{
    "claims_format": "stringified_json",
    "jwk_url": "https://cognito-idp.us-east-1.amazonaws.com/<user_pool_id>/.well-known/jwks.json",
    "type": "RS256"
}
0

There are 0 best solutions below