awslabs / aws-jwt-verify

JS library for verifying JWTs signed by Amazon Cognito, and any OIDC-compatible IDP that signs JWTs with RS256, RS384, and RS512
Apache License 2.0
598 stars 43 forks source link

Error: verifier.verify requires opts, but it is not required in docs. "Expected 2 arguments, but got 1" #90

Closed sandorduba closed 1 year ago

sandorduba commented 1 year ago

Hi, I'm trying to use this library in a brand-new Angular application to parse tokens.

"aws-jwt-verify": "^3.1.0",
"typescript": "~4.7.2"
Screenshot 2022-10-16 at 21 19 34

This isn't mentioned in any docs.

sandorduba commented 1 year ago

I downgraded the library to 2.0.0 and it works, but the versions above all require the opts.

EDIT: but using 2.0.0. resulting with another error:

Screenshot 2022-10-16 at 21 42 05
ottokruse commented 1 year ago

Web compatibility was added in v3.0.0 so if using in Angular stay at or above 3.

It seems you're running into a typing issue. If you don't specify tokenUse and clientId at verifier level, you must provide them in the options, the 2nd argument in the verify call. This is how it is supposed to work and TypeScript typings enforce this.

But you have defined both tokenUse and clientId at verifier level. However in your hover tooltip I see your IDE's type inference casts the verifier options object incorrectly as any, instead of as a proper object, which is why you're running into trouble I think.

Work around it by providing an verify properties object as second argument, in it adding clientId and tokenUse.

this.verifier.verify(value, {clientId:"<changeme>",tokenUse:"access"}

Solve it properly by making sure the object you pass into the create call can be properly typed by your IDE (so not as any). It might be because environment.clientId and environment.userPoolId in your case can't be properly typed, they should be string, so adding as string for both of them might work too:

this.verifier = CognitoJwtVerifier.create({
  userPoolId: environment.userPoolId as string,
  tokenUse: "access",
  clientId: environment.clientId as string,
})
sandorduba commented 1 year ago

Maybe. I want to save the verifier on the class level and I tried to give it a type. what should be the proper type of the verifier?

e.g. If I create it like

CognitoJwtVerifier.create({
  userPoolId: environment.userPoolId as string,
  tokenUse: "access",
  clientId: environment.clientId as string,
})
ottokruse commented 1 year ago

There's separate types for single-user-pool verifier and multi-user-pool verifier.

Easiest is to use the utility types from aws-jwt-verify/cognito-verifier:

import {
  CognitoJwtVerifierSingleUserPool,
  CognitoJwtVerifierMultiUserPool,
  CognitoJwtVerifier,
} from "aws-jwt-verify/cognito-verifier";

// Match the generic argument interface to what you actually want to pass in your `create` call later
let verifier: CognitoJwtVerifierSingleUserPool<{
  userPoolId: string;
  clientId: string;
  tokenUse: "access";
}>;

verifier = CognitoJwtVerifier.create({
  userPoolId: "changeme",
  clientId: "changeme",
  tokenUse: "access",
});
ottokruse commented 1 year ago

Did that help @sandorduba ?

ottokruse commented 1 year ago

Closing for now