Home > Net >  AWS Cognito JWT verification using Go Fiber middleware (getting "key is of invalid type")
AWS Cognito JWT verification using Go Fiber middleware (getting "key is of invalid type")

Time:09-14

I am getting "key is of invalid type" when I try to verify a Cognito based JWT in my middleware. Currently I set up the middle ware like this when the Fiber app is being setup:

// read the "jwks.json" that I got from AWS locally
signingKey, err := ioutil.ReadFile("./jwks.json")
if err != nil {
    log.Fatal("Error when opening file: ", err)
}

// pass in the signing key when middle ware is created
app.Get("/api", middleware.Protected(signingKey), handlers.ReadSomeData)

Then my middleware looks like this where most of it is from Go Fiber's JWT example repo.

func Protected(signingKey []byte) func(*fiber.Ctx) error {
    return jwtware.New(jwtware.Config{
        SigningKey:    signingKey,
        ErrorHandler:  jwtError,
        SigningMethod: "RS256",
    })
}

func jwtError(c *fiber.Ctx, err error) error {
    if err.Error() == "Missing or malformed JWT" {
        c.Status(fiber.StatusBadRequest)
        return c.JSON(fiber.Map{"status": "error", "message": err.Error(), "data": nil})

    } else {
        c.Status(fiber.StatusUnauthorized)
        return c.JSON(fiber.Map{"status": "error", "message": err.Error(), "data": nil})
    }
}

After an answer, I tried using the "SigningKeys" param but there was a type mismatch so I ended up reading in the jwks json file like so:

func Protected() func(*fiber.Ctx) error {

    signingKey, err := os.ReadFile("./jwks.json")
    if err != nil {

    }

    x := make(map[string]interface{})

    json.Unmarshal(signingKey, &x)

    return jwtware.New(jwtware.Config{
        SigningKeys:   x,
        ErrorHandler:  jwtError,
        SigningMethod: "RS256",
    })
}

However now my error is "Unexpected jwt key id=XXXXXXXXXXXX"

CodePudding user response:

It turns out fiber has a built-in functionality to pull the jwks.json data if you provide it a url to the keys. Probably there is also a method to make it load a local file, but with AWS keys you usually do not do it - keys may chnage depending on the environment you are in - production or test.

You need to know your AWS user pool region and that user pool's ID. That is normally provided in the user pool settings view, but you can easily come up with it based on the following example provided in AWS documentation:

https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json

For more see: AWS: Verifying a JSON web token

Here's a simple example to get it working with AWS Cognito JWT url:

    authMiddleware := jwtware.New(jwtware.Config{
        TokenLookup: "header:Authorization",
        AuthScheme:  "Bearer",
        KeySetURLs: []string{
            "https://cognito-idp.some-region-1.amazonaws.com/some-region-1_MYUserPoolId/.well-known/jwks.json",
        },
    })

    // Match any route
    app.Use(authMiddleware, func(c *fiber.Ctx) error {
        return c.SendString("           
  • Related