Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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"

like image 716
Anthony Pham Avatar asked Sep 04 '25 17:09

Anthony Pham


1 Answers

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("🥇 Yay!")
    })

    log.Fatal(app.Listen(":3000"))

You should now be able to test it with a request like this:

curl --location --request GET 'http://127.0.0.1:3000' \
--header 'Authorization: Bearer MyAWSJWTToken..'

Or with any HTTP client(like Postman). You must provide your JWT in a Authorization header.

See also:

  • JWT middleware for Fiber
like image 173
Klamber Avatar answered Sep 07 '25 17:09

Klamber