feat(): Add support for jwt asymetric keys (#12813)

* feat(): Add support for jwt asymetric keys

* Create early-chefs-chew.md

* fix unit tests

* Add verify options support

* feedback

* fix unit tests
This commit is contained in:
Adrien de Peretti
2025-06-25 10:29:32 +02:00
committed by GitHub
parent a833c3c98c
commit d517dbd66a
23 changed files with 813 additions and 43 deletions

View File

@@ -80,7 +80,21 @@ export class ConfigManager {
http.storeCors = http.storeCors ?? ""
http.adminCors = http.adminCors ?? ""
http.jwtOptions ??= {}
http.jwtOptions.expiresIn = http.jwtExpiresIn
http.jwtSecret = http?.jwtSecret ?? process.env.JWT_SECRET
http.jwtPublicKey = http?.jwtPublicKey ?? process.env.JWT_PUBLIC_KEY
if (
http?.jwtPublicKey &&
((http.jwtVerifyOptions && !http.jwtVerifyOptions.algorithms?.length) ||
(http.jwtOptions && !http.jwtOptions.algorithm))
) {
this.rejectErrors(
`JWT public key is provided but no algorithm is set in the 'jwtVerifyOptions' or 'jwtOptions' if 'jwtVerifyOptions' is not provided. It means that the algorithm will be inferred from the public key which can lead to missmatch and invalid algorithm errors.`
)
}
if (!http.jwtSecret) {
this.rejectErrors(

View File

@@ -1,7 +1,13 @@
import { ApiKeyDTO, IApiKeyModuleService } from "@medusajs/types"
import { ContainerRegistrationKeys, Modules } from "@medusajs/utils"
import { NextFunction, RequestHandler } from "express"
import { JwtPayload, verify } from "jsonwebtoken"
import type {
JwtPayload,
Secret,
SignOptions,
VerifyOptions,
} from "jsonwebtoken"
import { verify } from "jsonwebtoken"
import { ConfigModule } from "../../config"
import {
AuthContext,
@@ -76,7 +82,9 @@ export const authenticate = (
req.headers.authorization,
http.jwtSecret!,
authTypes,
actorTypes
actorTypes,
http.jwtPublicKey,
http.jwtVerifyOptions ?? http.jwtOptions
)
}
@@ -172,9 +180,11 @@ const getAuthContextFromSession = (
export const getAuthContextFromJwtToken = (
authHeader: string | undefined,
jwtSecret: string,
jwtSecret: Secret,
authTypes: AuthType[],
actorTypes: string[]
actorTypes: string[],
jwtPublicKey?: Secret,
jwtOptions?: VerifyOptions | SignOptions
): AuthContext | null => {
if (!authTypes.includes(BEARER_AUTH)) {
return null
@@ -195,7 +205,18 @@ export const getAuthContextFromJwtToken = (
// get config jwt secret
// verify token and set authUser
try {
const verified = verify(token, jwtSecret) as JwtPayload
const options = { ...jwtOptions } as VerifyOptions & SignOptions
if (!options.algorithms && options.algorithm) {
options.algorithms = [options.algorithm]
delete options.algorithm
}
const verified = verify(
token,
jwtPublicKey ?? jwtSecret!,
options
) as JwtPayload
if (isActorTypePermitted(actorTypes, verified.actor_type)) {
return verified as AuthContext
}