Written by Jason Xie on Feb 11, 2024.

AWS Cognito Authentication in Bun with ElysiaJS

A guide on how to set up AWS Cognito authentication in Bun with ElysiaJS

  1. Setup bearer and add a handler function that will be our authentication middleware to ElysiaJS
import bearer from "@elysiajs/bearer";
// import AuthMiddleware from ...

const router = new Elysia();

router.get("/health", HealthController.getHealth);

router.use(bearer());
router.onBeforeHandle([AuthMiddleware]);

router.get("/health-auth", HealthController.getHealth);
  1. Write the code for the AuthMiddleware

Before Feb 11, 2024

import jwt, { JwtPayload } from "jsonwebtoken";
import jwkToPem from "jwk-to-pem";

const getJwk = async (token: string) => {
  const decoded = jwt.decode(token, { complete: true }) as JwtPayload;
  const tokedKid = decoded.header.kid;
  const jwkUrl = decoded.payload.iss + "/.well-known/jwks.json";
  const jwks = await fetch(jwkUrl).then((res) => res.json());
  const jwk = jwks.keys.find((key: any) => key.kid === tokedKid);
  if (!jwk) throw new Error("JWK not found");
  return jwk;
};

export const AuthMiddleware = async (context: any) => {
  try {
    const { bearer } = context;
    if (!bearer) throw new Error("No token provided");

    const jwk = await getJwk(bearer);
    const publicKey = jwkToPem(jwk);

    const payload = jwt.verify(bearer, publicKey, { algorithms: ["RS256"] });

    context.userClaims = payload;
  } catch (error: any) {
    console.error("Token is invalid: ", error.message);
    return createResponse(401, { error: { message: "Unauthorized" } });
  }
};

After Feb 11, 2024 or when the fix is merged

Refer to the following links for more information:

import { CognitoJwtVerifier } from "aws-jwt-verify";

const cognitoJwtVerifier = CognitoJwtVerifier.create({
  userPoolId: process.env.AWS_COGNITO_USER_POOL_ID as string,
  tokenUse: "access",
});

export const AuthMiddleware = async (context: any) => {
  try {
    const { bearer } = context;
    if (!bearer) throw new Error("No token provided");

    const payload = await cognitoJwtVerifier.verify(bearer, {
      clientId: process.env.AWS_COGNITO_USER_CLIENT_ID as string,
    });

    context.userClaims = payload;
  } catch (error: any) {
    console.error("Token is invalid: ", error.message);
    return createResponse(401, { error: { message: "Unauthorized" } });
  }
};
  1. Results

No Auth /health no auth With Auth /health with auth