1
0

Compare commits

..

7 Commits

Author SHA1 Message Date
Leo Developer
318621ec1f allow using cryptokey directly 2024-01-18 20:43:50 +01:00
Richard Lee
55bc15bec4 Fix typing to make build work 2024-01-18 20:36:33 +01:00
kira924age
b0d4084a0f refactor: ๐Ÿ’ก reafactor decodePayload 2023-12-28 23:09:07 +01:00
kira924age
3fd594bbb5 feat: ๐ŸŽธ update decodePayload 2023-12-28 23:09:07 +01:00
kira924age
f8a216574a fix: ๐Ÿ› update decodePayload 2023-12-28 23:09:07 +01:00
kira924age
1f511549f5 feat: ๐ŸŽธ update decodePayload 2023-12-28 23:09:07 +01:00
Leo Developer
4be64469d3 fix header not being typed when using sign 2023-12-21 13:50:50 +01:00

View File

@@ -75,8 +75,8 @@ export type JwtOptions = {
* @extends JwtOptions
* @prop {JwtHeader} [header]
*/
export type JwtSignOptions = {
header?: JwtHeader
export type JwtSignOptions<T> = {
header?: JwtHeader<T>
} & JwtOptions
/**
@@ -198,7 +198,10 @@ async function importKey(key: string | JsonWebKey, algorithm: SubtleCryptoImport
function decodePayload<T = any>(raw: string): T | undefined {
try {
return JSON.parse(atob(raw))
const bytes = Array.from(atob(raw), char => char.charCodeAt(0));
const decodedString = new TextDecoder('utf-8').decode(new Uint8Array(bytes));
return JSON.parse(decodedString);
} catch {
return
}
@@ -208,22 +211,22 @@ function decodePayload<T = any>(raw: string): T | undefined {
* 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 {string | JsonWebKey | CryptoKey} 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 = {}>(payload: JwtPayload<Payload>, secret: string | JsonWebKey, options: JwtSignOptions | JwtAlgorithm = 'HS256'): Promise<string> {
export async function sign<Payload = {}, Header = {}>(payload: JwtPayload<Payload>, secret: string | JsonWebKey, options: JwtSignOptions<Header> | JwtAlgorithm = 'HS256'): Promise<string> {
if (typeof options === 'string')
options = { algorithm: options }
options = { algorithm: 'HS256', header: { typ: 'JWT' }, ...options }
options = { algorithm: 'HS256', header: { typ: 'JWT' } as JwtHeader<Header>, ...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')
throw new Error('secret must be a string, a JWK object or a CryptoKey object')
if (typeof options.algorithm !== 'string')
throw new Error('options.algorithm must be a string')
@@ -238,7 +241,7 @@ export async function sign<Payload = {}>(payload: JwtPayload<Payload>, secret: s
const partialToken = `${textToBase64Url(JSON.stringify({ ...options.header, alg: options.algorithm }))}.${textToBase64Url(JSON.stringify(payload))}`
const key = await importKey(secret, algorithm)
const key = secret instanceof CryptoKey ? secret : await importKey(secret, algorithm)
const signature = await crypto.subtle.sign(algorithm, key, textToArrayBuffer(partialToken))
return `${partialToken}.${arrayBufferToBase64Url(signature)}`
@@ -248,12 +251,12 @@ export async function sign<Payload = {}>(payload: JwtPayload<Payload>, secret: s
* 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 {string | JsonWebKey | CryptoKey} 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 async function verify(token: string, secret: string | JsonWebKey, options: JwtVerifyOptions | JwtAlgorithm = { algorithm: 'HS256', throwError: false }): Promise<boolean> {
export async function verify(token: string, secret: string | JsonWebKey | CryptoKey, options: JwtVerifyOptions | JwtAlgorithm = { algorithm: 'HS256', throwError: false }): Promise<boolean> {
if (typeof options === 'string')
options = { algorithm: options, throwError: false }
@@ -263,7 +266,7 @@ export async function verify(token: string, secret: string | JsonWebKey, options
throw new Error('token must be a string')
if (typeof secret !== 'string' && typeof secret !== 'object')
throw new Error('secret must be a string or a JWK object')
throw new Error('secret must be a string, a JWK object or a CryptoKey object')
if (typeof options.algorithm !== 'string')
throw new Error('options.algorithm must be a string')
@@ -290,7 +293,7 @@ export async function verify(token: string, secret: string | JsonWebKey, options
if (payload.exp && payload.exp <= Math.floor(Date.now() / 1000))
throw new Error('EXPIRED')
const key = await importKey(secret, algorithm)
const key = secret instanceof CryptoKey ? secret : await importKey(secret, algorithm)
return await crypto.subtle.verify(algorithm, key, base64UrlToArrayBuffer(tokenParts[2]), textToArrayBuffer(`${tokenParts[0]}.${tokenParts[1]}`))
} catch(err) {
@@ -318,4 +321,4 @@ export default {
sign,
verify,
decode
}
}