Support JWK format
This commit is contained in:
36
src/index.ts
36
src/index.ts
@@ -1,6 +1,18 @@
|
|||||||
if (typeof crypto === 'undefined' || !crypto.subtle)
|
if (typeof crypto === 'undefined' || !crypto.subtle)
|
||||||
throw new Error('SubtleCrypto not supported!')
|
throw new Error('SubtleCrypto not supported!')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef JwkPayload
|
||||||
|
*/
|
||||||
|
export interface JwkPayload extends Object {
|
||||||
|
"crv": string,
|
||||||
|
"d": string,
|
||||||
|
"ext": boolean,
|
||||||
|
"key_ops": string[],
|
||||||
|
"kty": string,
|
||||||
|
"x": string,
|
||||||
|
"y": string
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* @typedef JwtAlgorithm
|
* @typedef JwtAlgorithm
|
||||||
* @type {'ES256'|'ES384'|'ES512'|'HS256'|'HS384'|'HS512'|'RS256'|'RS384'|'RS512'}
|
* @type {'ES256'|'ES384'|'ES512'|'HS256'|'HS384'|'HS512'|'RS256'|'RS384'|'RS512'}
|
||||||
@@ -176,7 +188,7 @@ function _decodePayload(raw: string): JwtHeader | JwtPayload | null {
|
|||||||
* @throws {Error} If there's a validation issue.
|
* @throws {Error} If there's a validation issue.
|
||||||
* @returns {Promise<string>} Returns token as a `string`.
|
* @returns {Promise<string>} Returns token as a `string`.
|
||||||
*/
|
*/
|
||||||
export async function sign(payload: JwtPayload, secret: string, options: JwtSignOptions | JwtAlgorithm = { algorithm: 'HS256', header: { typ: 'JWT' } }): Promise<string> {
|
export async function sign(payload: JwtPayload, secret: string | JwkPayload, options: JwtSignOptions | JwtAlgorithm = { algorithm: 'HS256', header: { typ: 'JWT' } }): Promise<string> {
|
||||||
if (typeof options === 'string')
|
if (typeof options === 'string')
|
||||||
options = { algorithm: options, header: { typ: 'JWT' } }
|
options = { algorithm: options, header: { typ: 'JWT' } }
|
||||||
|
|
||||||
@@ -185,8 +197,8 @@ export async function sign(payload: JwtPayload, secret: string, options: JwtSign
|
|||||||
if (payload === null || typeof payload !== 'object')
|
if (payload === null || typeof payload !== 'object')
|
||||||
throw new Error('payload must be an object')
|
throw new Error('payload must be an object')
|
||||||
|
|
||||||
if (typeof secret !== 'string')
|
if (typeof secret !== 'string' && typeof secret !== 'object')
|
||||||
throw new Error('secret must be a string')
|
throw new Error('secret must be a string or a JWK object')
|
||||||
|
|
||||||
if (typeof options.algorithm !== 'string')
|
if (typeof options.algorithm !== 'string')
|
||||||
throw new Error('options.algorithm must be a string')
|
throw new Error('options.algorithm must be a string')
|
||||||
@@ -203,7 +215,10 @@ export async function sign(payload: JwtPayload, secret: string, options: JwtSign
|
|||||||
const partialToken = `${base64UrlStringify(_utf8ToUint8Array(JSON.stringify({ ...options.header, alg: options.algorithm })))}.${base64UrlStringify(_utf8ToUint8Array(payloadAsJSON))}`
|
const partialToken = `${base64UrlStringify(_utf8ToUint8Array(JSON.stringify({ ...options.header, alg: options.algorithm })))}.${base64UrlStringify(_utf8ToUint8Array(payloadAsJSON))}`
|
||||||
let keyFormat = 'raw'
|
let keyFormat = 'raw'
|
||||||
let keyData
|
let keyData
|
||||||
if (secret.startsWith('-----BEGIN')) {
|
if (typeof secret === 'object') {
|
||||||
|
keyFormat = 'jwk';
|
||||||
|
keyData = secret;
|
||||||
|
} else if (typeof secret === 'string' && secret.startsWith('-----BEGIN')) {
|
||||||
keyFormat = 'pkcs8'
|
keyFormat = 'pkcs8'
|
||||||
keyData = _str2ab(secret.replace(/-----BEGIN.*?-----/g, '').replace(/-----END.*?-----/g, '').replace(/\s/g, ''))
|
keyData = _str2ab(secret.replace(/-----BEGIN.*?-----/g, '').replace(/-----END.*?-----/g, '').replace(/\s/g, ''))
|
||||||
} else
|
} else
|
||||||
@@ -223,7 +238,7 @@ export async function sign(payload: JwtPayload, secret: string, options: JwtSign
|
|||||||
* @throws {Error | string} Throws an error `string` if the token is invalid or an `Error-Object` if there's a validation issue.
|
* @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`.
|
* @returns {Promise<boolean>} Returns `true` if signature, `nbf` (if set) and `exp` (if set) are valid, otherwise returns `false`.
|
||||||
*/
|
*/
|
||||||
export async function verify(token: string, secret: string, options: JwtVerifyOptions | JwtAlgorithm = { algorithm: 'HS256', throwError: false }): Promise<boolean> {
|
export async function verify(token: string, secret: string | JwkPayload, options: JwtVerifyOptions | JwtAlgorithm = { algorithm: 'HS256', throwError: false }): Promise<boolean> {
|
||||||
if (typeof options === 'string')
|
if (typeof options === 'string')
|
||||||
options = { algorithm: options, throwError: false }
|
options = { algorithm: options, throwError: false }
|
||||||
|
|
||||||
@@ -232,8 +247,8 @@ export async function verify(token: string, secret: string, options: JwtVerifyOp
|
|||||||
if (typeof token !== 'string')
|
if (typeof token !== 'string')
|
||||||
throw new Error('token must be a string')
|
throw new Error('token must be a string')
|
||||||
|
|
||||||
if (typeof secret !== 'string')
|
if (typeof secret !== 'string' && typeof secret !== 'object')
|
||||||
throw new Error('secret must be a string')
|
throw new Error('secret must be a string or a JWK object')
|
||||||
|
|
||||||
if (typeof options.algorithm !== 'string')
|
if (typeof options.algorithm !== 'string')
|
||||||
throw new Error('options.algorithm must be a string')
|
throw new Error('options.algorithm must be a string')
|
||||||
@@ -272,8 +287,11 @@ export async function verify(token: string, secret: string, options: JwtVerifyOp
|
|||||||
}
|
}
|
||||||
let keyFormat = 'raw'
|
let keyFormat = 'raw'
|
||||||
let keyData
|
let keyData
|
||||||
if (secret.startsWith('-----BEGIN')) {
|
if (typeof secret === 'object') {
|
||||||
keyFormat = 'spki'
|
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, ''))
|
keyData = _str2ab(secret.replace(/-----BEGIN.*?-----/g, '').replace(/-----END.*?-----/g, '').replace(/\s/g, ''))
|
||||||
} else
|
} else
|
||||||
keyData = _utf8ToUint8Array(secret)
|
keyData = _utf8ToUint8Array(secret)
|
||||||
|
|||||||
Reference in New Issue
Block a user