diff --git a/packages/common/lib/jwt/JwkThumbprint.ts b/packages/common/lib/jwt/JwkThumbprint.ts index 190d66e4..c1bbc9ef 100644 --- a/packages/common/lib/jwt/JwkThumbprint.ts +++ b/packages/common/lib/jwt/JwkThumbprint.ts @@ -1,70 +1,70 @@ -import * as u8a from 'uint8arrays' +import * as u8a from 'uint8arrays'; -import { DigestAlgorithm } from '../types' +import { DigestAlgorithm } from '../types'; -import { JWK } from '.' +import { JWK } from '.'; const check = (value: unknown, description: string) => { if (typeof value !== 'string' || !value) { - throw Error(`${description} missing or invalid`) + throw Error(`${description} missing or invalid`); } -} +}; const digest = async (algorithm: DigestAlgorithm, data: Uint8Array) => { - const subtleDigest = `SHA-${algorithm.slice(-3)}` - return new Uint8Array(await crypto.subtle.digest(subtleDigest, data)) -} + const subtleDigest = `SHA-${algorithm.slice(-3)}`; + return new Uint8Array(await crypto.subtle.digest(subtleDigest, data)); +}; export async function calculateJwkThumbprint(jwk: JWK, digestAlgorithm?: DigestAlgorithm): Promise { if (!jwk || typeof jwk !== 'object') { - throw new TypeError('JWK must be an object') + throw new TypeError('JWK must be an object'); } - const algorithm = digestAlgorithm ?? 'sha256' + const algorithm = digestAlgorithm ?? 'sha256'; if (algorithm !== 'sha256' && algorithm !== 'sha384' && algorithm !== 'sha512') { - throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"') + throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"'); } - let components + let components; switch (jwk.kty) { case 'EC': - check(jwk.crv, '"crv" (Curve) Parameter') - check(jwk.x, '"x" (X Coordinate) Parameter') - check(jwk.y, '"y" (Y Coordinate) Parameter') - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y } - break + check(jwk.crv, '"crv" (Curve) Parameter'); + check(jwk.x, '"x" (X Coordinate) Parameter'); + check(jwk.y, '"y" (Y Coordinate) Parameter'); + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }; + break; case 'OKP': - check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter') - check(jwk.x, '"x" (Public Key) Parameter') - components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x } - break + check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter'); + check(jwk.x, '"x" (Public Key) Parameter'); + components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x }; + break; case 'RSA': - check(jwk.e, '"e" (Exponent) Parameter') - check(jwk.n, '"n" (Modulus) Parameter') - components = { e: jwk.e, kty: jwk.kty, n: jwk.n } - break + check(jwk.e, '"e" (Exponent) Parameter'); + check(jwk.n, '"n" (Modulus) Parameter'); + components = { e: jwk.e, kty: jwk.kty, n: jwk.n }; + break; case 'oct': - check(jwk.k, '"k" (Key Value) Parameter') - components = { k: jwk.k, kty: jwk.kty } - break + check(jwk.k, '"k" (Key Value) Parameter'); + components = { k: jwk.k, kty: jwk.kty }; + break; default: - throw Error('"kty" (Key Type) Parameter missing or unsupported') + throw Error('"kty" (Key Type) Parameter missing or unsupported'); } - const data = u8a.fromString(JSON.stringify(components), 'utf-8') - return u8a.toString(await digest(algorithm, data), 'base64url') + const data = u8a.fromString(JSON.stringify(components), 'utf-8'); + return u8a.toString(await digest(algorithm, data), 'base64url'); } export async function getDigestAlgorithmFromJwkThumbprintUri(uri: string): Promise { - const match = uri.match(/^urn:ietf:params:oauth:jwk-thumbprint:sha-(\w+):/) + const match = uri.match(/^urn:ietf:params:oauth:jwk-thumbprint:sha-(\w+):/); if (!match) { - throw new Error(`Invalid JWK thumbprint URI structure ${uri}`) + throw new Error(`Invalid JWK thumbprint URI structure ${uri}`); } - const algorithm = `sha${match[1]}` as DigestAlgorithm + const algorithm = `sha${match[1]}` as DigestAlgorithm; if (algorithm !== 'sha256' && algorithm !== 'sha384' && algorithm !== 'sha512') { - throw new Error(`Invalid JWK thumbprint URI digest algorithm ${uri}`) + throw new Error(`Invalid JWK thumbprint URI digest algorithm ${uri}`); } - return algorithm + return algorithm; } export async function calculateJwkThumbprintUri(jwk: JWK, digestAlgorithm: DigestAlgorithm = 'sha256'): Promise { - const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm) - return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}` + const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm); + return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`; } diff --git a/packages/common/lib/jwt/Jwt.types.ts b/packages/common/lib/jwt/Jwt.types.ts index d24a74df..1b2f3b90 100644 --- a/packages/common/lib/jwt/Jwt.types.ts +++ b/packages/common/lib/jwt/Jwt.types.ts @@ -1,20 +1,20 @@ -import { JwtHeader as jwtDecodeJwtHeader, JwtPayload as jwtDecodePayload } from 'jwt-decode' +import { JwtHeader as jwtDecodeJwtHeader, JwtPayload as jwtDecodePayload } from 'jwt-decode'; -import { JWK } from '.' +import { JWK } from '.'; export type JwtHeader = jwtDecodeJwtHeader & { - alg?: string - x5c?: string[] - kid?: string - jwk?: JWK - jwt?: string -} & Record + alg?: string; + x5c?: string[]; + kid?: string; + jwk?: JWK; + jwt?: string; +} & Record; export type JwtPayload = jwtDecodePayload & { - client_id?: string - nonce?: string - request_uri?: string - client_id_scheme?: string -} & Record + client_id?: string; + nonce?: string; + request_uri?: string; + client_id_scheme?: string; +} & Record; export enum SigningAlgo { EDDSA = 'EdDSA', diff --git a/packages/did-auth-siop-adapter/lib/DidJwtAdapter.ts b/packages/did-auth-siop-adapter/lib/DidJwtAdapter.ts index a33a7ecc..2605e21f 100644 --- a/packages/did-auth-siop-adapter/lib/DidJwtAdapter.ts +++ b/packages/did-auth-siop-adapter/lib/DidJwtAdapter.ts @@ -1,6 +1,6 @@ +import { JwtHeader, JwtPayload } from '@sphereon/common' import { AuthorizationRequestPayload, IDTokenPayload, JwtIssuerWithContext, RequestObjectPayload } from '@sphereon/did-auth-siop' import { JwtVerifier } from '@sphereon/did-auth-siop' -import { JwtHeader, JwtPayload } from '@sphereon/common' import { Resolvable } from 'did-resolver' import { getAudience, getSubDidFromPayload, signIDTokenPayload, signRequestObjectPayload, validateLinkedDomainWithDid, verifyDidJWT } from './did'