Generate keys and export a JWK with jose
Asymmetric keys let one service sign tokens with a private key while others verify them with the public key, often shared as a JWK.
How it works
- Generate the key pair.
generateKeyPair('ES256')returns apublicKeyand aprivateKey. The private key signs, the public key verifies. [1] - Sign and verify. The code signs a JWT with the private key and
alg: 'ES256', then passes the public key tojwtVerifyand prints the verified subject. [1] - Export as JWK.
exportJWK(publicKey)gives a plain JSON Web Key object, printed field by field. The code also prints the result ofcalculateJwkThumbprintfor that key. [1]
Run and edit it
It runs in your browser, in a sandboxed frame that cannot see this site; the packages load from esm.sh only after you press Run.
import { generateKeyPair, SignJWT, jwtVerify, exportJWK, calculateJwkThumbprint } from 'jose'
const { publicKey, privateKey } = await generateKeyPair('ES256')
console.log('public key type:', publicKey.type)
console.log('private key type:', privateKey.type)
const jwt = await new SignJWT({ scope: 'read:reports' })
.setProtectedHeader({ alg: 'ES256' })
.setSubject('service-a')
.setExpirationTime('5m')
.sign(privateKey)
console.log('token:', jwt.slice(0, 40) + '...')
const { payload } = await jwtVerify(jwt, publicKey)
console.log('verified sub:', payload.sub, '| scope:', payload.scope)
const jwk = await exportJWK(publicKey)
console.log('public JWK:')
for (const [key, value] of Object.entries(jwk)) {
console.log(' ' + key + ':', value)
}
console.log('thumbprint:', await calculateJwkThumbprint(jwk))
Change 'ES256' to 'PS256' in both places and see the exported JWK fields change. Code written by AgentGid [1].
Change 'ES256' to 'PS256' in both places and see the exported JWK fields change. Code written by AgentGid [1].Checked Oct 12, 2026: it starts without errors in Chromium with jose 6.2.12. Needs WebGL.
More jose examples
Sign a JWT with jose Verify a JWT with jose Decode a JWT with jose Encrypt and decrypt a JWT with jose
Sources
Explanations written by AgentGid from the official docs; the numbers in brackets point here. The code marked "written by AgentGid" is ours and free to copy.