mirror of
https://github.com/hanzoai/jose.git
synced 2026-09-24 17:00:01 +00:00
refactor: parse a Protected Header in one place
Add parseJoseHeader and use it to decode and validate protected headers for JWS, JWE, and decodeProtectedHeader. Signed-off-by: Filip Skokan <[email protected]>
This commit is contained in:
+20
-1
@@ -1,5 +1,6 @@
|
||||
import { decode } from '../util/base64url.js'
|
||||
import { encode } from './buffer_utils.js'
|
||||
import { encode, strictDecoder } from './buffer_utils.js'
|
||||
import { isObject } from './type_checks.js'
|
||||
|
||||
export const unprotected: unique symbol = Symbol()
|
||||
|
||||
@@ -44,3 +45,21 @@ export async function digest(
|
||||
const subtleDigest = `SHA-${algorithm.slice(-3)}`
|
||||
return new Uint8Array(await crypto.subtle.digest(subtleDigest, data as Uint8Array<ArrayBuffer>))
|
||||
}
|
||||
|
||||
/** Base64url decode, UTF-8 decode, JSON parse, and require a JSON object - in one place. */
|
||||
export function parseJoseHeader<T>(
|
||||
b64: string,
|
||||
ErrorClass: new (message: string) => Error,
|
||||
message: string,
|
||||
): T {
|
||||
let parsed: unknown
|
||||
try {
|
||||
parsed = JSON.parse(strictDecoder.decode(decode(b64)))
|
||||
} catch {
|
||||
throw new ErrorClass(message)
|
||||
}
|
||||
if (!isObject(parsed)) {
|
||||
throw new ErrorClass(message)
|
||||
}
|
||||
return parsed as T
|
||||
}
|
||||
|
||||
+3
-10
@@ -1,11 +1,10 @@
|
||||
import type * as types from '../types.d.ts'
|
||||
import { decode as b64u } from '../util/base64url.js'
|
||||
import { decrypt, generateCek } from './content_encryption.js'
|
||||
import { decodeBase64url, encodeBase64url } from './helpers.js'
|
||||
import { decodeBase64url, encodeBase64url, parseJoseHeader } from './helpers.js'
|
||||
import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../util/errors.js'
|
||||
import { isDisjoint, isObject } from './type_checks.js'
|
||||
import { decryptKeyManagement } from './key_management.js'
|
||||
import { concat, decoder, encode, strictDecoder } from './buffer_utils.js'
|
||||
import { concat, decoder, encode } from './buffer_utils.js'
|
||||
import { validateCrit, validateAlgorithms, JWE_RECOGNIZED } from './options.js'
|
||||
import { normalizeKey } from './normalize_key.js'
|
||||
import { jweAlgorithm, jweEncryption } from './jwe_algorithms.js'
|
||||
@@ -89,13 +88,7 @@ export function checkRecipient(jwe: types.FlattenedJWE): void {
|
||||
export function shareJWE(jwe: types.FlattenedJWE): SharedJWE {
|
||||
let parsedProt: types.JWEHeaderParameters | undefined
|
||||
if (jwe.protected) {
|
||||
try {
|
||||
const protectedHeader = b64u(jwe.protected)
|
||||
parsedProt = JSON.parse(strictDecoder.decode(protectedHeader))
|
||||
if (!isObject(parsedProt)) throw new Error()
|
||||
} catch {
|
||||
throw new JWEInvalid('JWE Protected Header is invalid')
|
||||
}
|
||||
parsedProt = parseJoseHeader(jwe.protected, JWEInvalid, 'JWE Protected Header is invalid')
|
||||
}
|
||||
|
||||
const protectedHeader: Uint8Array =
|
||||
|
||||
+4
-11
@@ -1,11 +1,10 @@
|
||||
import type * as types from '../types.d.ts'
|
||||
import { decode as b64u } from '../util/base64url.js'
|
||||
import { verify } from './signing.js'
|
||||
import { jwsAlgorithm } from './jws_algorithms.js'
|
||||
import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../util/errors.js'
|
||||
import { concat, decoder, encoder, encode, strictDecoder } from './buffer_utils.js'
|
||||
import { decodeBase64url, encodeBase64url } from './helpers.js'
|
||||
import { isDisjoint, isObject } from './type_checks.js'
|
||||
import { concat, decoder, encoder, encode } from './buffer_utils.js'
|
||||
import { decodeBase64url, encodeBase64url, parseJoseHeader } from './helpers.js'
|
||||
import { isDisjoint } from './type_checks.js'
|
||||
import { checkKeyType } from './check_key_type.js'
|
||||
import { validateCrit, validateAlgorithms, JWS_RECOGNIZED } from './options.js'
|
||||
import { normalizeKey } from './normalize_key.js'
|
||||
@@ -71,13 +70,7 @@ export async function verifySignature(
|
||||
): Promise<VerifiedSignature> {
|
||||
let parsedProt: types.JWSHeaderParameters = {}
|
||||
if (jws.protected) {
|
||||
try {
|
||||
const protectedHeader = b64u(jws.protected)
|
||||
parsedProt = JSON.parse(strictDecoder.decode(protectedHeader))
|
||||
if (!isObject(parsedProt)) throw new Error()
|
||||
} catch {
|
||||
throw new JWSInvalid('JWS Protected Header is invalid')
|
||||
}
|
||||
parsedProt = parseJoseHeader(jws.protected, JWSInvalid, 'JWS Protected Header is invalid')
|
||||
}
|
||||
|
||||
let joseHeader: types.JWSHeaderParameters
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
* @module
|
||||
*/
|
||||
|
||||
import { decode as b64u } from './base64url.js'
|
||||
import { strictDecoder } from '../lib/buffer_utils.js'
|
||||
import { isObject } from '../lib/type_checks.js'
|
||||
import { parseJoseHeader } from '../lib/helpers.js'
|
||||
import type * as types from '../types.d.ts'
|
||||
|
||||
/** JWE and JWS Header Parameters */
|
||||
@@ -43,16 +41,11 @@ export function decodeProtectedHeader(token: string | object): ProtectedHeaderPa
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof protectedB64u !== 'string' || !protectedB64u) {
|
||||
throw new Error()
|
||||
}
|
||||
const result = JSON.parse(strictDecoder.decode(b64u(protectedB64u!)))
|
||||
if (!isObject(result)) {
|
||||
throw new Error()
|
||||
}
|
||||
return result as ProtectedHeaderParameters
|
||||
} catch {
|
||||
throw new TypeError('Invalid Token or Protected Header formatting')
|
||||
const invalid = 'Invalid Token or Protected Header formatting'
|
||||
|
||||
if (typeof protectedB64u !== 'string' || !protectedB64u) {
|
||||
throw new TypeError(invalid)
|
||||
}
|
||||
|
||||
return parseJoseHeader<ProtectedHeaderParameters>(protectedB64u, TypeError, invalid)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user