Created
February 9, 2022 07:02
-
-
Save jayg-hive/4bffead5c685ae3bc13b4b32aa7966f8 to your computer and use it in GitHub Desktop.
Cognito JWT Validation via JOSE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createRemoteJWKSet, jwtVerify } from "jose"; | |
import type { JWTPayload } from "jose"; | |
import { AWS_REGION, COGNITO_USER_POOL_ID, COGNITO_WEB_CLIENT_ID } from "../utils/consts"; | |
const cognitoIssuer = `https://cognito-idp.${AWS_REGION}.amazonaws.com/${COGNITO_USER_POOL_ID}`; | |
const cognitoPublicJwks = `${cognitoIssuer}/.well-known/jwks.json`; | |
interface AWSAuth extends JWTPayload { | |
"cognito:groups": string[]; | |
client_id: string; | |
origin_jti: string; | |
event_id: string; | |
token_use: string; | |
scope: string; | |
username: string; | |
} | |
// Reference: https://aws.amazon.com/premiumsupport/knowledge-center/decode-verify-cognito-json-token/ | |
export async function verifyJwtToken( | |
jwtAccessToken: string, | |
// requestUsername: string // some requests provide this (i.e., via CognitoIdentityServiceProvider cookies), validation for this can be otherwise skipped. | |
): Promise<boolean> { | |
try { | |
const jwks = createRemoteJWKSet(new URL(cognitoPublicJwks)); | |
// verify if the token is valid | |
const { payload } = await jwtVerify(jwtAccessToken, jwks, {}); | |
if (!payload) throw new Error("Failed verifying this token."); | |
const { iss, username, client_id: clientId } = payload as AWSAuth; | |
// verify if correct issuer is given | |
if (iss !== cognitoIssuer) throw new Error("Invalid issuer"); | |
// verify if request is from the correct client | |
if (clientId !== COGNITO_WEB_CLIENT_ID) throw new Error("Invalid web client"); | |
// verify if request is from the same username | |
// if (requestUsername !== username) throw new Error("User doesn't match"); | |
return true; | |
} catch (error) { | |
// do error handling stuff here | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Notes:
exp
field can be destructured from the payload.req.cookies
. See this file for an example of how it's extracted.username
can be extracted via theLastAuthUser
key; it can then be passed to the above for added validation.