Skip to content

Commit

Permalink
Add caching and jwks clients configurations
Browse files Browse the repository at this point in the history
  • Loading branch information
Viktor-K committed Sep 30, 2024
1 parent 8b29574 commit 9652505
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
decodeJwtToken,
userRoles,
verifyJwtToken,
getJwksClient,
} from "pagopa-interop-commons";
import { TenantId, genericError, unsafeBrandId } from "pagopa-interop-models";
import { config } from "../config/config.js";
Expand Down Expand Up @@ -53,6 +54,8 @@ export function authorizationServiceBuilder(
allowList: string[],
rateLimiter: RateLimiter
) {
const jwksClients = getJwksClient();

const readJwt = async (
identityToken: string,
logger: Logger
Expand All @@ -61,7 +64,7 @@ export function authorizationServiceBuilder(
sessionClaims: SessionClaims;
selfcareId: string;
}> => {
const verified = await verifyJwtToken(identityToken, logger);
const verified = await verifyJwtToken(identityToken, jwksClients, logger);
if (!verified) {
throw tokenVerificationFailed();
}
Expand Down
6 changes: 4 additions & 2 deletions packages/commons/src/auth/authenticationMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
unauthorizedError,
} from "pagopa-interop-models";
import { P, match } from "ts-pattern";
import { ExpressContext } from "../index.js";
import { ExpressContext, getJwksClient } from "../index.js";
import { Logger, logger } from "../logging/index.js";
import { AuthData } from "./authData.js";
import { Headers } from "./headers.js";
Expand All @@ -18,6 +18,8 @@ const makeApiProblem = makeApiProblemBuilder({});
export const authenticationMiddleware: ZodiosRouterContextRequestHandler<
ExpressContext
> = async (req, res, next): Promise<unknown> => {
const jwksClients = getJwksClient();

const addCtxAuthData = async (
authHeader: string,
logger: Logger
Expand All @@ -34,7 +36,7 @@ export const authenticationMiddleware: ZodiosRouterContextRequestHandler<
}

const jwtToken = authorizationHeader[1];
const valid = await verifyJwtToken(jwtToken, logger);
const valid = await verifyJwtToken(jwtToken, jwksClients, logger);
if (!valid) {
throw unauthorizedError("Invalid token");
}
Expand Down
16 changes: 16 additions & 0 deletions packages/commons/src/auth/jwk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
notAllowedCertificateException,
notAllowedPrivateKeyException,
} from "pagopa-interop-models";
import jwksClient, { JwksClient } from "jwks-rsa";
import { JWTConfig } from "../config/index.js";

export const decodeBase64ToPem = (base64String: string): string => {
try {
Expand Down Expand Up @@ -64,3 +66,17 @@ export function sortJWK(jwk: JsonWebKey): JsonWebKey {
{}
);
}

export function getJwksClient(): JwksClient[] {
const config = JWTConfig.parse(process.env);
return config.wellKnownUrls.map((url) =>
jwksClient({
cache: true,
cacheMaxEntries: 5,
timeout: 30000,
cacheMaxAge: 600000, // 10 minutes
jwksRequestsPerMinute: 10,
jwksUri: url,
})
);
}
14 changes: 5 additions & 9 deletions packages/commons/src/auth/jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,30 +61,26 @@ const getKey = async (

export const verifyJwtToken = async (
jwtToken: string,
jwksClients: jwksClient.JwksClient[],
logger: Logger
): Promise<boolean> => {
const config = JWTConfig.parse(process.env);
const clients = config.wellKnownUrls.map((url) =>
jwksClient({
jwksUri: url,
})
);

try {
const { acceptedAudiences } = JWTConfig.parse(process.env);

const jwtHeader = decodeJwtTokenHeaders(jwtToken, logger);
if (!jwtHeader?.kid) {
logger.warn("Token verification failed: missing kid");
return Promise.reject(false);
}

const secret: Secret = await getKey(clients, jwtHeader.kid, logger);
const secret: Secret = await getKey(jwksClients, jwtHeader.kid, logger);

return new Promise((resolve, _reject) => {
jwt.verify(
jwtToken,
secret,
{
audience: config.acceptedAudiences,
audience: acceptedAudiences,
},
function (err, _decoded) {
if (err) {
Expand Down

0 comments on commit 9652505

Please sign in to comment.