# panva/jose: JWT, JWS and JWE for Node.js, Browsers and Workers

> panva/jose is a zero-dependency TypeScript module for JSON Web Tokens, signatures, encryption and key handling across Node.js, Deno, Bun, browsers and Cloudflare Workers. It gives you the primitives, not an auth framework, and that distinction decides whether it fits your stack.

**panva/jose** — JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes

- Repository: https://github.com/panva/jose
- Stars: 7,812 · Forks: 377
- Language: TypeScript
- License: MIT
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/panva-jose

## What panva/jose actually solves

The README describes jose as "a JavaScript module for JSON Object Signing and Encryption, providing support for JSON Web Tokens (JWT), JSON Web Signature (JWS), JSON Web Encryption (JWE), JSON Web Key (JWK), JSON Web Key Set (JWKS), and more." That list is the scope. It is a standards implementation, not an authentication product.

The audience is narrower than the runtime list suggests. You are the right reader if you already know what a compact JWS looks like and you need to produce or verify one in code that runs unchanged on a server and on an edge worker. The README states the module is "compatible with JavaScript runtimes that support the utilized Web API globals and standard built-in objects or are Node.js," and names Bun, browsers, Cloudflare Workers, Deno, Electron and Node.js as supported, adding that the list is not exhaustive.

What it does not do is equally important. There is no session store, no user database, no login redirect, and no opinion about where a token should be kept on the client. A team looking for "JWT authentication" in the product sense will find the pieces here and still have to assemble the rest.

## The JOSE primitive set: JWA, JWS, JWE, JWK and JWKS

The module is organised by the standard it implements, and the README's documentation index mirrors that split. JWT handling covers claims set validation and signature verification through jwtVerify, signing through the SignJWT class, and decoding helpers decodeProtectedHeader and decodeJwt, which the README notes are for use "prior to its validation." Encrypted tokens follow the same shape with jwtDecrypt and EncryptJWT.

Below the token layer sit the raw JOSE operations. JWS signing and verification are exposed per serialization: CompactSign, FlattenedSign and GeneralSign for signing, and compactVerify, flattenedVerify and generalVerify for verification, matching the serializations in RFC 7515 Section 7. JWE mirrors this with CompactEncrypt, FlattenedEncrypt and GeneralEncrypt, plus compactDecrypt, flattenedDecrypt and generalDecrypt, per RFC 7516 Section 7. Both the JWS and JWE verification paths can take a remote or local JWKS.

Key handling is the third layer. Import functions cover JWK, SPKI public keys, X.509 certificates and PKCS #8 private keys. Generation covers asymmetric key pairs and symmetric secrets. Export covers JWK, PKCS #8 and SPKI. The README also lists thumbprint calculation, a thumbprint URI, verification using a JWK embedded in a JWS header, the UnsecuredJWT class, and a dedicated JOSE errors reference.

That breadth is the reason the package can replace several smaller libraries at once. It is also why the API surface is large enough that reading the typedoc index is faster than guessing method names.

## Installing panva/jose and verifying your first token

The README says jose is distributed via npmjs.com, jsr.io, jsdelivr.com and github.com. For a Node.js or bundler-based project the npm package is the usual route. The package.json shows the package name is jose, the version at the time of writing is 6.2.12, and the license is MIT.

```bash
npm install jose
```

After installation, the README's own example shows the import style, which is ESM:

```js
import * as jose from 'jose'
```

The package.json sets "type": "module" and marks the package as side-effect free, so ESM is the expected consumption path. The README's dependency section states the module "has no dependencies and it exports tree-shakeable ESM," with a footnote marker on CommonJS that the truncated README does not expand.

For a first real use, the documented entry point for validating an incoming token is jwtVerify. The README lists it under "JWT Claims Set Validation & Signature Verification" and points to createRemoteJWKSet for the case where the keys live behind a JWKS endpoint and createLocalJWKSet for keys you already hold. A verification call therefore needs two things: a key material source, and the token. If you are checking a token issued by an identity provider that publishes a JWKS URL, createRemoteJWKSet is the documented path; if you control the keys, import them and use the local set.

One thing the README does not document is a rollback procedure for a bad upgrade. The CHANGELOG.md file exists at the repository root, so version history is tracked there, but the README itself gives no downgrade guidance.

## Where the runtime story gets complicated

The promise is one module across many runtimes, and the README supports that with a list and a caveat: "Please note that certain algorithms ma" is where the supplied text cuts off, which means the README does contain an algorithm caveat that is not fully visible here. Treat that sentence as the thing to read in full before you plan around a specific algorithm.

The practical consequence is that "works on Cloudflare Workers" and "works on Node.js" are not the same claim as "every algorithm works identically everywhere." Web Crypto availability differs by runtime, and jose is built on the Web API globals rather than on Node's crypto module. If your design depends on a particular curve or a particular key wrapping mode, verify it against the Supported Runtimes section for each runtime you target, not just against the one you develop on.

A second boundary: jose is a library, not a service. Key rotation, JWKS hosting, and cache lifetime for a remote JWKS are your responsibility. createRemoteJWKSet fetches keys; deciding how long to trust them, and what to do when a fetch fails, is application logic. Teams that expect the library to handle that will be disappointed, and the README does not present it as handling it.

## panva/jose versus jsonwebtoken and jwt-decode

The most common comparison is with jsonwebtoken, and the difference is architectural rather than cosmetic. jsonwebtoken is a Node.js library built around Node's crypto module and CommonJS. jose is ESM-first, dependency-free, and targets Web-interoperable runtimes through Web API globals, which is why the same code can run in a browser, a Cloudflare Worker and Node.js.

The second comparison is with jwt-decode, which the package.json keyword list includes. jwt-decode reads a token's claims without verifying the signature. jose ships decodeJwt and decodeProtectedHeader for the same purpose, but the README explicitly frames them as utilities for use "prior to its validation," and the verification functions live alongside them in the same module. If you only ever need to read claims on a client that already trusts the token, the smaller library is a reasonable choice. If you need the verification step in the same codebase, splitting across two packages buys nothing.

A third comparison appears in search data: Nimbus JOSE JWT. That is a JVM library for the same standards family. The difference is the platform contract. Nimbus serves Java and Kotlin services; jose serves JavaScript runtimes. If your token issuer is a Java service and your verifier is a Worker, you may end up running both, and the interoperability comes from the JOSE standards themselves rather than from either library.

## Maintenance, licence and the cost of upgrading

The repository is not archived, and the last push was on 2026-09-21. Recent releases listed are v6.2.12 on 2026-09-05, v6.2.11 on 2026-09-04, and v6.2.10 on 2026-08-21. Patch releases at that cadence suggest fixes are landing regularly, and the version history is recorded in CHANGELOG.md at the repository root.

The licence is MIT, declared in both LICENSE.md and package.json. MIT is permissive: it allows commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is a description of the licence text, not legal advice, and if your organisation has a policy on attribution or on bundled notices, route it through whoever handles that.

The upgrade cost has two components. First, the module is ESM with "type": "module" and a structured exports map covering subpaths like ./key/import and ./key/export. A CommonJS consumer relying on require will need to check how the exports map resolves, and the README's CommonJS footnote is the place that discussion lives. Second, because jose implements standards rather than a product surface, a major version can change how a primitive is called without any change to the token format itself. The CHANGELOG.md is the file to read before bumping a major. The README does not describe a migration path.

## Conclusion

Adopt panva/jose when you need JOSE primitives that behave the same in Node.js, Deno, Bun, browsers and Cloudflare Workers, or when you want remote JWKS verification without pulling in a framework. Do not adopt it if you want session storage, a login UI, or an opinionated auth flow; jose stops at the token layer. Before committing, check the Supported Runtimes section of the README against your exact runtime, and confirm that the algorithms you plan to use are not among those the README says certain runtimes do not support.

## FAQ

### What is the difference between JWT and JOSE in panva/jose?

JOSE is the umbrella family of standards, and JWT is one thing built on it. The README describes jose as a module for JSON Object Signing and Encryption covering JWT, JWS, JWE, JWK and JWKS, so JWT support sits inside the broader JOSE implementation rather than replacing it.

### What is JWS used for in panva/jose?

JWS covers digital signature and MAC computation and validation over arbitrary payloads, not just token claims. The README lists signing and verification classes for the compact, flattened JSON and general JSON serializations, matching RFC 7515 Section 7.

### How can I decode a JWT payload using panva/jose?

The README lists decodeJwt for decoding a JWT Claims Set and decodeProtectedHeader for the protected header, describing both as utilities for use prior to validation. Verification is a separate step through jwtVerify.

## Sources

- [Issues](https://github.com/panva/jose/issues)
- [License: MIT](https://github.com/panva/jose/blob/main/LICENSE)
- [panva/jose on GitHub](https://github.com/panva/jose)
- [README](https://github.com/panva/jose/blob/main/README.md)
- [Releases](https://github.com/panva/jose/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/panva-jose
