| .github/ISSUE_TEMPLATE | ||
| docs | ||
| lib | ||
| test | ||
| .gitignore | ||
| .npmrc | ||
| .travis.yml | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| LICENSE.md | ||
| LICENSE_THIRD_PARTY | ||
| package.json | ||
| README.md | ||
@panva/jose
"JSON Web Almost Everything" - JWA, JWS, JWE, JWT, JWK, JWKS for Node.js with minimal dependencies
Implemented specs & features
The following specifications are implemented by @panva/jose
- JSON Web Signature (JWS) - RFC7515
- JSON Web Encryption (JWE) - RFC7516
- JSON Web Key (JWK) - RFC7517
- JSON Web Algorithms (JWA) - RFC7518
- JSON Web Token (JWT) - RFC7519
- JSON Web Key (JWK) Thumbprint - RFC7638
- JWS Unencoded Payload Option - RFC7797
The test suite utilizes examples defined in RFC7520 to confirm its JOSE implementation is correct.
Detailed feature matrix (Click to expand)
Legend:
- ✓ Implemented
- ✕ Missing node crypto support / won't implement
- ◯ not planned (yet?) / PR / Use-Case first welcome
| JWK Key Types | Supported | |
|---|---|---|
| RSA | ✓ | RSA |
| Elliptic Curve | ✓ | EC |
| Octet sequence | ✓ | oct |
| Serialization | JWS Sign | JWS Verify | JWE Encrypt | JWE Decrypt |
|---|---|---|---|---|
| Compact | ✓ | ✓ | ✓ | ✓ |
| General JSON | ✓ | ✓ | ✓ | ✓ |
| Flattened JSON | ✓ | ✓ | ✓ | ✓ |
| JWS Algorithms | Supported | |
|---|---|---|
| RSASSA-PKCS1-v1_5 | ✓ | RS256, RS384, RS512 |
| RSASSA-PSS | ✓ | PS256, PS384, PS512 |
| ECDSA | ✓ | ES256, ES384, ES512 |
| HMAC with SHA-2 | ✓ | HS256, HS384, HS512 |
| JWE Key Management Algorithms | Supported | |
|---|---|---|
| AES | ✓ | A128KW, A192KW, A256KW |
| AES GCM | ✓ | A128GCMKW, A192GCMKW, A256GCMKW |
| Direct Key Agreement | ✓ | dir |
| RSAES OAEP | ✓* | RSA-OAEP (*RSA-OAEP-256 is not supported due to its lack of support in Node.JS) |
| RSAES-PKCS1-v1_5 | ✓ | RSA1_5 |
| PBES2 | ✓ | PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW |
| ECDH-ES | ✓ | ECDH-ES, ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW |
| JWE Content Encryption Algorithms | Supported | |
|---|---|---|
| AES GCM | ✓ | A128GCM, A192GCM, A256GCM |
| AES_CBC_HMAC_SHA2 | ✓ | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 |
Pending Node.js Support 🤞:
- RFC8037 (EdDSA, OKP kty, etc)
crypto.getCurves().includes('Curve25519')// => 😢crypto.getCurves().includes('Curve448')// => 😢openssl ecparam -list_curves// => 😢
Won't implement:
- ✕ JWS embedded key / referenced verification
- one can decode the header and pass the (
x5c,jwk) toJWK.importKeyand validate with that key, similarly the application can handle fetching and then instantiating the referencedx5uorjkuin its own code. This way you opt-in to these behaviours and forx5cspecifically the recipient is responsible for validating the certificate chain is trusted
- one can decode the header and pass the (
- ✕ JWS detached content
- one can remove/attach the payload after/before the respective operation
- ✕ "none" alg support
- no crypto, no use
Not Planned / PR | Use-Case | Discussion Welcome:
- ◯ automatically adding
kidreference to JWS / JWE Headers - ◯
x5c,x5t,x5t#S256,x5uetcJWK.Keyfields
Have a question about using @panva/jose? - ask.
Found a bug? - report it.
Missing a feature? - If it wasn't already discussed before, ask for it.
Found a vulnerability? - Reach out to us via email first, see security vulnerability disclosure.
Support
If you or your business use @panva/jose, please consider becoming a Patron so I can continue maintaining it and adding new features carefree. You may also donate one-time via PayPal.
![]()
Documentation
Usage
⚠️ Minimal Node.js version required is v11.8.0 ⚠️ The plan is to release v1.0.0 when Node.js v12.0.0 releases in April 2019
Installing @panva/jose
npm install @panva/jose
Usage
const jose = require('@panva/jose')
const {
JWE, // JSON Web Encryption (JWE)
JWK, // JSON Web Key (JWK)
JWKS, // JSON Web Key Set (JWKS)
JWS, // JSON Web Signature (JWS)
JWT, // JSON Web Token (JWT)
errors // errors utilized by @panva/jose
} = jose
Keys and KeyStores
Prepare your Keys and KeyStores. See the documentation for more.
const key = jose.JWK.importKey(fs.readFileSync('path/to/key/file'))
const jwk = { kty: 'EC',
kid: 'dl4M_fcI7XoFCsQ22PYrQBkuxZ2pDcbDimcdFmmXM98',
crv: 'P-256',
x: 'v37avifcL-xgh8cy6IFzcINqqmFLc2JF20XUpn4Y2uQ',
y: 'QTwy27XgP7ZMOdGOSopAHB-FU1JMQn3J9GEWGtUXreQ' }
const anotherKey = jose.JWK.importKey(jwk)
const keystore = new jose.JWK.KeyStore(key, key2)
JWT vs JWS
The JWT module provides IANA registered claim type and format validations on top of JWS as well as convenience options for verifying UNIX timestamps, setting maximum allowed JWT age, verifying audiences, and more.
The JWS module on the other hand handles the other JWS Serialization Syntaxes with all their additional available features and allows signing of any payload, i.e. not just serialized JSON objects.
JWT Signing
Sign with a private or symmetric key with plethora of convenience options. See the documentation for more.
jose.JWT.sign(
{ 'urn:example:claim': 'foo' },
privateKey,
{
expiresIn: '1 hour',
issuer: 'https://op.example.com',
audience: 'urn:example:client_id',
header: {
typ: 'JWT'
},
algorithm: 'PS256'
}
)
JWT Verification
Verify with a public or symmetric key with plethora of convenience options. See the documentation for more.
jose.JWT.verify(
'eyJ0eXAiOiJKV1QiLCJhbGciOiJQUzI1NiIsImtpZCI6IjRQQXBsVkJIN0toS1ZqN0xob0RFM0VVQnNGc0hvaTRhSmxBZGstM3JuME0ifQ.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6ImZvbyIsImF1ZCI6InVybjpleGFtcGxlOmNsaWVudF9pZCIsImlzcyI6Imh0dHBzOi8vb3AuZXhhbXBsZS5jb20iLCJpYXQiOjE1NTEyOTI2MjksImV4cCI6MTU1MTI5NjIyOX0.nE5fgRL8gvlStf_wB4mJ0TSXVmhJRnUVQuZ0ts6a1nWnnk0Rv69bEJ12BoMdpyPrGa_W6dxU4HFj89F4pQwW0kqBK2-TZ_n9lq-iqupj46w_lpKOfPC3clVc7ZmqYF81bEA-nX93cSKqVV-qPNPEFenb8XHKszYhBFu_uiRg9rXj2qXVU7PXGJAGTzhVgVxB-3XDB1bQ_6KiDCwzVPftrHxEYLydRCaHzggDg6sAFUhQqhPguKuE2gs6jVUh_gIL2RXeoLoinx6gZ72rfovaOmud-yzNIUN8Tvo0pqBmx0s_lEhTlfrQCzN7hZNmV1eG0GDDE-S_CfZhPePnVJZoRA',
publicKey,
{
issuer: 'https://op.example.com',
audience: 'urn:example:client_id',
algorithms: ['PS256']
}
)
JWS Signing
Sign with a private or symmetric key using compact serialization. See the documentation for more.
jose.JWS.sign(
{ sub: 'johndoe' },
privateKey
)
JWS Verifying
Verify with a public or symmetric key. See the documentation for more.
jose.JWS.verify(
'eyJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJqb2huZG9lIn0.T_SYLQV3A5_kFDDVNuoadoURSEtuSOR-dG2CMmrP-ULK9xbIf2vYeiHOkvTrnqGlWEGBGxYtsP1VkXmNsi1uOw',
publicKey
)
JWE Encrypting
Encrypt using the recipient's public key or a shared symmetrical secret. See the documentation for more.
jose.JWE.encrypt(
'eyJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJqb2huZG9lIn0.T_SYLQV3A5_kFDDVNuoadoURSEtuSOR-dG2CMmrP-ULK9xbIf2vYeiHOkvTrnqGlWEGBGxYtsP1VkXmNsi1uOw',
publicKey
)
JWE Verifying
Decrypt using the private key or a shared symmetrical secret. See the documentation for more.
jose.JWE.decrypt(
'eyJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiRUNESC1FUyIsImVwayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2IiwieCI6IkVsUGhsN1ljTVZsWkhHM0daSkRoOVJhemNYYlN2VFNheUF6aTBINFFtRUEiLCJ5IjoiM0hDREJTRy12emd6cGtLWmJqMU05UzVuUEJrTDBBdFM4U29ORUxMWE1SayJ9fQ..FhmidRo0twvFA7jcfKFNJw.o112vgiG_qUL1JR5WHpsErcxxgaK_FAa7vCWJ--WulndLpdwdRXHd9k3aL_k8K67xoAThrt10d7dSY2TlPpHdYkw979u0V-C4TNrpzNkv5jpBjU6hHyKpoGZfEsiTD1ivHaFy3ZLCTS69kN_eVKsZGLVf_dkq6Sz6bWE4-ln_fuwukPyMvjTyaTreLjPLBZW.ocKwptCm4Zn437L5hWFnHg',
privateKey
)
FAQ
Semver?
Yes. Everything that's either exported in the TypeScript definitions file or documented is subject to Semantic Versioning 2.0.0. The rest is to be considered private API and is subject to change between any versions.
How do I use it outside of Node.js
It is only built for Node.js environment - it builds on top of the crypto module and requires
the KeyObject API that was added in Node.js v11.6.0.
How is it different from node-jose
node-jose is built to work in any javascript runtime, to be able to do that it packs a lot of
backfill and javascript implementation code in the form of
node-forge, this significantly increases the footprint
of the module with dependencies that either aren't ever used or have native implementation available
in Node.js already, those are often times faster and more reliable.
How is it different from node-jws or node-jwa?
- it is providing Key and KeyStore abstractions
- there is JSON Web Encryption support
- there is no asynchronous API since node crypto is ultimately entirely synchronous
- it supports all JWS / JWE Serialization Syntaxes
What is the ultimate goal?
- No dependencies, the moment JWK formatted keys are supported by node's
cryptothe direct dependency count will go down from 1 to 0. 🚀 - Just the API one needs, having used other jose modules for 3+ years I only include what's useful
Why? Just, why?
I was / (still am) using node-jose for
openid-client and
oidc-provider and came to realize its shortcomings
in terms of performance and API (not having well defined errors). When Node.js v12 lands in April
2019 I will be releasing new major versions of both those libraries using @panva/jose.
+ this was an amazing opportunity to learn JOSE as a whole