npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@geostrategists/cdk-jwks-rotation

v3.0.0

Published

CDK construct for generating and rotating JWT signing keys and JSON Web Key Sets (JWKS)

Readme

CDK JWKS Rotation Construct

This AWS CDK construct creates and manages cryptographic key pairs for signing JSON Web Tokens (JWTs). It stores the private key securely in AWS Secrets Manager and publishes the public key as a JWKS (JSON Web Key Set) file in an S3 bucket. The construct provides seamless, automated key rotation.

There is a blog post by Jan Brennenstuhl at Zalando which nicely explains the general concept.

The construct uses AWS Secrets Manager rotation to manage the lifecycle of the keys. Whenever a new key is rotated in, the next key is already generated, and its public key is added to the JWKS file. This allows consumers to have refetched the JWKS in time, and be prepared when the next key is activated. The next key is stored in the same secret in a separate version labeled "NEXT". Whenever a key is retired and the maximum token lifetime has passed, the corresponding public key is removed from the JWKS file (after a configurable grace period).

Installation

npm install @geostrategists/cdk-jwks-rotation
# or
yarn add @geostrategists/cdk-jwks-rotation

Types

SecretValue

The SecretValue interface represents the structure of cryptographic key data stored in AWS Secrets Manager:

interface SecretValue {
  /** The private key in PEM format used for signing JWTs */
  privateKeyPem: string;
  /** The public key in JWK format for inclusion in JWKS */
  publicKeyJwk: JWK;
  /** Unique key identifier used in JWT headers and JWKS */
  kid: string;
  /** Algorithm used for signing (e.g., RS256, ES256) */
  alg: string;
  /** ISO timestamp when the key was created */
  createdAt: string;
  /** ISO timestamp when the key was activated for signing (optional) */
  activatedAt?: string;
}

Usage

Mandatory Props

  • secretName: Name for the AWS Secrets Manager secret to store the private key.
  • keySpec: Specification for the key pair (algorithm, curve, modulus length, etc.). See jose documentation
  • maxTokenValidityDuration: Maximum duration for which a token signed by a key is considered valid. This will influence how long a retired key is kept in the JWKS file.

Optional Props

  • bucket: Existing S3 bucket to store the JWKS file. By default, a new bucket will be created.
  • bucketPath: Path/name for the JWKS file in the bucket. Default: ".well-known/jwks.json".
  • bucketName: Name for a new S3 bucket (if bucket is not provided). By default, a name will be generated by CKD (recommended).
  • rotationInterval: How often to rotate keys. Default: Duration.days(60).
  • minActivationGracePeriod: Grace period before a new key is activated. Default: Duration.days(7).
  • cleanupCheckInterval: How often to check for old keys to clean up. (Doing this too often can influence costs). Default: Duration.hours(24).
  • minKeyCleanupGracePeriod: Grace period before deleting old keys after max token validity duration has passed. Default: Duration.hours(6).
import { JwksRotation } from 'cdk-jwks-rotation';

new JwksRotation(this, 'JwksRotation', {
  secretName: 'my-jwks-secret',
  keySpec: { algorithm: 'ES256' },
  maxTokenValidityDuration: Duration.seconds(3600),
  // Optional, these are the default values:
  bucket: undefined, // or: myBucket,
  bucketPath: ".well-known/jwks.json",
  rotationInterval: Duration.days(60),
  minActivationGracePeriod: Duration.days(7),
  cleanupCheckInterval: Duration.hours(24),
  minKeyCleanupGracePeriod: Duration.hours(6),
});

IAM and permissions

The construct grants the rotation Lambda:

  • Secrets Manager: DescribeSecret, GetSecretValue, PutSecretValue, UpdateSecretVersionStage (scoped to the created secret)
  • S3 bucket read/write for the JWKS object

Troubleshooting

  • Rotation aborted with "Next key is too new": Allow more time (per minActivationGracePeriod) between creating NEXT and a rotation cycle, or lower the grace period if appropriate.
  • "No keys found in JWKS document": Ensure initial deployment updated JWKS; re-run rotation or check Lambda permissions to S3.
  • JWT verification failed during testSecret: Verify the JWKS URL and that the new public key was written; check S3 object and cache.

Potential issues / room for improvement (as identified by AI)

  • Bucket exposure flexibility: Consider a prop to toggle bucket publicReadAccess and optionally attach a CloudFront distribution for best practice public serving.
  • Custom KMS support: Allow passing a customer-managed KMS key for the secret.
  • JWKS cache-control configuration: Make CacheControl configurable to align with consumer caching SLAs.
  • Health endpoint: Optionally emit a small metric or a health-check log/CloudWatch metric on successful rotation to aid monitoring/alerts.
  • Key ID strategy: Current kid uses nanoid(). Some teams prefer deterministic KIDs (e.g., hash of public key). Consider making strategy pluggable.
  • Broader algorithm validation: Enforce that ES algorithms are paired with a required crv, and validate modulus length ranges for RSA in the construct props.

Development

Install and scripts:

yarn install
yarn lint
yarn typecheck
yarn build
yarn test:run