Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@tsndr/cloudflare-worker-jwt

Package Overview
Dependencies
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tsndr/cloudflare-worker-jwt - npm Package Compare versions

Comparing version 2.2.7 to 2.2.8

20

index.d.ts

@@ -95,2 +95,12 @@ /// <reference types="@cloudflare/workers-types" />

/**
* Verifies the integrity of the token and returns a boolean value.
*
* @param {string} token The token string generated by `jwt.sign()`.
* @param {string | JsonWebKey} secret The string which was used to sign the payload.
* @param {JWTVerifyOptions | JWTAlgorithm} options The options object or the algorithm.
* @throws {Error | string} Throws an error `string` if the token is invalid or an `Error-Object` if there's a validation issue.
* @returns {Promise<boolean>} Returns `true` if signature, `nbf` (if set) and `exp` (if set) are valid, otherwise returns `false`.
*/
export declare function verify(token: string, secret: string | JsonWebKey, options?: JwtVerifyOptions | JwtAlgorithm): Promise<boolean>;
/**
* Signs a payload and returns the token

@@ -106,12 +116,2 @@ *

/**
* Verifies the integrity of the token and returns a boolean value.
*
* @param {string} token The token string generated by `jwt.sign()`.
* @param {string | JsonWebKey} secret The string which was used to sign the payload.
* @param {JWTVerifyOptions | JWTAlgorithm} options The options object or the algorithm.
* @throws {Error | string} Throws an error `string` if the token is invalid or an `Error-Object` if there's a validation issue.
* @returns {Promise<boolean>} Returns `true` if signature, `nbf` (if set) and `exp` (if set) are valid, otherwise returns `false`.
*/
export declare function verify(token: string, secret: string | JsonWebKey, options?: JwtVerifyOptions | JwtAlgorithm): Promise<boolean>;
/**
* Returns the payload **without** verifying the integrity of the token. Please use `jwt.verify()` first to keep your application secure!

@@ -118,0 +118,0 @@ *

if (typeof crypto === 'undefined' || !crypto.subtle)
throw new Error('SubtleCrypto not supported!');
function base64UrlParse(s) {
// @ts-ignore
return new Uint8Array(Array.prototype.map.call(atob(s.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '')), c => c.charCodeAt(0)));
// return new Uint8Array(Array.from(atob(s.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, ''))).map(c => c.charCodeAt(0)))
}
function base64UrlStringify(a) {
// @ts-ignore
return btoa(String.fromCharCode.apply(0, a)).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
// return btoa(String.fromCharCode.apply(0, Array.from(a))).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_')
}
const algorithms = {

@@ -24,18 +14,79 @@ ES256: { name: 'ECDSA', namedCurve: 'P-256', hash: { name: 'SHA-256' } },

};
function _utf8ToUint8Array(str) {
return base64UrlParse(btoa(unescape(encodeURIComponent(str))));
function bytesToByteString(bytes) {
let byteStr = '';
for (let i = 0; i < bytes.byteLength; i++) {
byteStr += String.fromCharCode(bytes[i]);
}
return byteStr;
}
function _str2ab(str) {
str = atob(str);
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
function byteStringToBytes(byteStr) {
let bytes = new Uint8Array(byteStr.length);
for (let i = 0; i < byteStr.length; i++) {
bytes[i] = byteStr.charCodeAt(i);
}
return buf;
return bytes;
}
function _decodePayload(raw) {
function arrayBufferToBase64String(arrayBuffer) {
const byteArray = new Uint8Array(arrayBuffer);
const byteStr = bytesToByteString(byteArray);
return btoa(byteStr);
}
function base64StringToArrayBuffer(b64str) {
const byteStr = atob(b64str);
const bytes = byteStringToBytes(byteStr);
return bytes.buffer;
}
function textToArrayBuffer(str) {
const buf = decodeURI(encodeURIComponent(str)); // 2 bytes for each char
const bytes = byteStringToBytes(buf);
return bytes;
}
// @ts-ignore
function arrayBufferToText(arrayBuffer) {
const byteArray = new Uint8Array(arrayBuffer);
const byteStr = bytesToByteString(byteArray);
return byteStr;
}
function arrayBufferToBase64Url(arrayBuffer) {
return arrayBufferToBase64String(arrayBuffer).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
}
function base64UrlToArrayBuffer(b64url) {
return base64StringToArrayBuffer(b64url.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, ''));
}
function textToBase64Url(str) {
return btoa(str).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
}
function pemToBinary(pem) {
return base64StringToArrayBuffer(pem.replace(/-+(BEGIN|END).*/g, '').replace(/\s/g, ''));
}
async function importTextSecret(key, algorithm) {
return await crypto.subtle.importKey("raw", textToArrayBuffer(key), algorithm, true, ["verify", "sign"]);
}
async function importJwk(key, algorithm) {
return await crypto.subtle.importKey("jwk", key, algorithm, true, ["verify", "sign"]);
}
async function importPublicKey(key, algorithm) {
return await crypto.subtle.importKey("spki", pemToBinary(key), algorithm, true, ["verify"]);
}
async function importPrivateKey(key, algorithm) {
return await crypto.subtle.importKey("pkcs8", pemToBinary(key), algorithm, true, ["sign"]);
}
async function importKey(key, algorithm) {
if (typeof key === 'object')
return importJwk(key, algorithm);
if (typeof key !== 'string')
throw new Error('Unsupported key type!');
if (key.includes('PUBLIC'))
return importPublicKey(key, algorithm);
if (key.includes('PRIVATE'))
return importPrivateKey(key, algorithm);
return importTextSecret(key, algorithm);
}
function decodePayload(raw) {
switch (raw.length % 4) {
case 0:
break;
case 1:
raw += '===';
break;
case 2:

@@ -48,6 +99,6 @@ raw += '==';

default:
throw new Error('Illegal base64url string!');
throw new Error('Invalid base64url string!');
}
try {
return JSON.parse(decodeURIComponent(escape(atob(raw))));
return JSON.parse(atob(raw));
}

@@ -59,44 +110,2 @@ catch {

/**
* Signs a payload and returns the token
*
* @param {JwtPayload} payload The payload object. To use `nbf` (Not Before) and/or `exp` (Expiration Time) add `nbf` and/or `exp` to the payload.
* @param {string | JsonWebKey} secret A string which is used to sign the payload.
* @param {JwtSignOptions | JwtAlgorithm | string} [options={ algorithm: 'HS256', header: { typ: 'JWT' } }] The options object or the algorithm.
* @throws {Error} If there's a validation issue.
* @returns {Promise<string>} Returns token as a `string`.
*/
export async function sign(payload, secret, options = { algorithm: 'HS256', header: { typ: 'JWT' } }) {
if (typeof options === 'string')
options = { algorithm: options, header: { typ: 'JWT' } };
options = { algorithm: 'HS256', header: { typ: 'JWT' }, ...options };
if (payload === null || typeof payload !== 'object')
throw new Error('payload must be an object');
if (typeof secret !== 'string' && typeof secret !== 'object')
throw new Error('secret must be a string or a JWK object');
if (typeof options.algorithm !== 'string')
throw new Error('options.algorithm must be a string');
const algorithm = algorithms[options.algorithm];
if (!algorithm)
throw new Error('algorithm not found');
if (!payload.iat)
payload.iat = Math.floor(Date.now() / 1000);
const payloadAsJSON = JSON.stringify(payload);
const partialToken = `${base64UrlStringify(_utf8ToUint8Array(JSON.stringify({ ...options.header, alg: options.algorithm })))}.${base64UrlStringify(_utf8ToUint8Array(payloadAsJSON))}`;
let keyFormat = 'raw';
let keyData;
if (typeof secret === 'object') {
keyFormat = 'jwk';
keyData = secret;
}
else if (typeof secret === 'string' && secret.startsWith('-----BEGIN')) {
keyFormat = 'pkcs8';
keyData = _str2ab(secret.replace(/-----BEGIN.*?-----/g, '').replace(/-----END.*?-----/g, '').replace(/\s/g, ''));
}
else
keyData = _utf8ToUint8Array(secret);
const key = await crypto.subtle.importKey(keyFormat, keyData, algorithm, false, ['sign']);
const signature = await crypto.subtle.sign(algorithm, key, _utf8ToUint8Array(partialToken));
return `${partialToken}.${base64UrlStringify(new Uint8Array(signature))}`;
}
/**
* Verifies the integrity of the token and returns a boolean value.

@@ -142,18 +151,35 @@ *

}
let keyFormat = 'raw';
let keyData;
if (typeof secret === 'object') {
keyFormat = 'jwk';
keyData = secret;
}
else if (typeof secret === 'string' && secret.startsWith('-----BEGIN')) {
keyFormat = 'spki';
keyData = _str2ab(secret.replace(/-----BEGIN.*?-----/g, '').replace(/-----END.*?-----/g, '').replace(/\s/g, ''));
}
else
keyData = _utf8ToUint8Array(secret);
const key = await crypto.subtle.importKey(keyFormat, keyData, algorithm, false, ['verify']);
return await crypto.subtle.verify(algorithm, key, base64UrlParse(tokenParts[2]), _utf8ToUint8Array(`${tokenParts[0]}.${tokenParts[1]}`));
const key = await importKey(secret, algorithm);
return await crypto.subtle.verify(algorithm, key, base64UrlToArrayBuffer(tokenParts[2]), textToArrayBuffer(`${tokenParts[0]}.${tokenParts[1]}`));
}
/**
* Signs a payload and returns the token
*
* @param {JwtPayload} payload The payload object. To use `nbf` (Not Before) and/or `exp` (Expiration Time) add `nbf` and/or `exp` to the payload.
* @param {string | JsonWebKey} secret A string which is used to sign the payload.
* @param {JwtSignOptions | JwtAlgorithm | string} [options={ algorithm: 'HS256', header: { typ: 'JWT' } }] The options object or the algorithm.
* @throws {Error} If there's a validation issue.
* @returns {Promise<string>} Returns token as a `string`.
*/
export async function sign(payload, secret, options = 'HS256') {
if (typeof options === 'string')
options = { algorithm: options };
options = { algorithm: 'HS256', header: { typ: 'JWT' }, ...options };
if (!payload || typeof payload !== 'object')
throw new Error('payload must be an object');
if (!secret || (typeof secret !== 'string' && typeof secret !== 'object'))
throw new Error('secret must be a string or a JWK object');
if (typeof options.algorithm !== 'string')
throw new Error('options.algorithm must be a string');
const algorithm = algorithms[options.algorithm];
if (!algorithm)
throw new Error('algorithm not found');
if (!payload.iat)
payload.iat = Math.floor(Date.now() / 1000);
const partialToken = `${textToBase64Url(JSON.stringify({ ...options.header, alg: options.algorithm }))}.${textToBase64Url(JSON.stringify(payload))}`;
const key = await importKey(secret, algorithm);
const signature = await crypto.subtle.sign(algorithm, key, textToArrayBuffer(partialToken));
return `${partialToken}.${arrayBufferToBase64Url(signature)}`;
}
/**
* Returns the payload **without** verifying the integrity of the token. Please use `jwt.verify()` first to keep your application secure!

@@ -166,4 +192,4 @@ *

return {
header: _decodePayload(token.split('.')[0].replace(/-/g, '+').replace(/_/g, '/')),
payload: _decodePayload(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'))
header: decodePayload(token.split('.')[0].replace(/-/g, '+').replace(/_/g, '/')),
payload: decodePayload(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'))
};

@@ -170,0 +196,0 @@ }

{
"name": "@tsndr/cloudflare-worker-jwt",
"version": "2.2.7",
"version": "2.2.8",
"description": "A lightweight JWT implementation with ZERO dependencies for Cloudflare Worker",

@@ -5,0 +5,0 @@ "main": "index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc