Skip to content

Commit

Permalink
fix: incorporate feedback
Browse files Browse the repository at this point in the history
Signed-off-by: Martin Auer <[email protected]>
  • Loading branch information
auer-martin committed Feb 10, 2025
1 parent 5ec2bad commit 84a8dec
Show file tree
Hide file tree
Showing 57 changed files with 1,031 additions and 734 deletions.
2 changes: 1 addition & 1 deletion packages/oauth2/src/Oauth2AuthorizationServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export interface Oauth2AuthorizationServerOptions {
/**
* Callbacks required for the oauth2 authorization server
*/
callbacks: Omit<CallbackContext, 'decryptJwt' | 'encryptJwe'>
callbacks: Omit<CallbackContext, 'decryptJwe' | 'encryptJwe'>
}

export class Oauth2AuthorizationServer {
Expand Down
2 changes: 1 addition & 1 deletion packages/oauth2/src/Oauth2Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export interface Oauth2ClientOptions {
/**
* Callbacks required for the oauth2 client
*/
callbacks: Omit<CallbackContext, 'verifyJwt' | 'clientAuthentication' | 'decryptJwt' | 'encryptJwe'>
callbacks: Omit<CallbackContext, 'verifyJwt' | 'clientAuthentication' | 'decryptJwe' | 'encryptJwe'>
}

export class Oauth2Client {
Expand Down
22 changes: 9 additions & 13 deletions packages/oauth2/src/callbacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,23 @@ export type VerifyJwtCallback = (
}
>

export interface DecryptJwtCallbackOptions {
export interface DecryptJweCallbackOptions {
jwk: Jwk
}

export type DecryptJwtCallback = (
export type DecryptJweCallback = (
jwe: string,
options?: DecryptJwtCallbackOptions
options?: DecryptJweCallbackOptions
) => OrPromise<
| {
decrypted: true
decryptionJwk: Jwk
payload: string
header: JwtHeader
}
| {
decrypted: false
decryptionJwk?: Jwk
payload?: string
header?: JwtHeader
}
>

Expand Down Expand Up @@ -91,7 +89,7 @@ export interface CallbackContext {
/**
* Decrypt jwe callback for decrypting of Json Web Encryptions
*/
decryptJwt: DecryptJwtCallback
decryptJwe: DecryptJweCallback

/**
* Encrypt jwt callback for encrypting of Json Web Encryptions
Expand Down Expand Up @@ -125,12 +123,10 @@ export interface CallbackContext {
clientAuthentication: ClientAuthenticationCallback

/**
* Get the DNS names from a X.509 certificate
* Get the DNS names and URI names from a X.509 certificate
*/
getX509SanDnsNames?: (certificate: string) => string[]

/**
* Get the URI names from a X.509 certificate
*/
getX509SanUriNames?: (certificate: string) => string[]
getX509CertificateMetadata?: (certificate: string) => {
sanDnsNames: string[]
sanUriNames: string[]
}
}
8 changes: 4 additions & 4 deletions packages/oauth2/src/common/jwt/decode-jwt-header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
stringToJsonWithErrorHandling,
} from '@openid4vc/utils'
import { Oauth2JwtParseError } from '../../error/Oauth2JwtParseError'
import type { InferSchemaOutput } from './decode-jwt'
import type { InferSchemaOrDefaultOutput } from './decode-jwt'
import { zJwtHeader } from './z-jwt'

export interface DecodeJwtHeaderOptions<HeaderSchema extends BaseSchema | undefined> {
Expand All @@ -23,7 +23,7 @@ export interface DecodeJwtHeaderOptions<HeaderSchema extends BaseSchema | undefi
}

export type DecodeJwtHeaderResult<HeaderSchema extends BaseSchema | undefined = undefined> = {
header: InferSchemaOutput<HeaderSchema, typeof zJwtHeader>
header: InferSchemaOrDefaultOutput<HeaderSchema, typeof zJwtHeader>
}

export function decodeJwtHeader<HeaderSchema extends BaseSchema | undefined = undefined>(
Expand All @@ -41,10 +41,10 @@ export function decodeJwtHeader<HeaderSchema extends BaseSchema | undefined = un
'Unable to parse jwt header to JSON'
)
} catch (error) {
throw new Oauth2JwtParseError('Error parsing JWT')
throw new Oauth2JwtParseError(`Error parsing JWT. ${error instanceof Error ? error.message : ''}`)
}

const header = parseWithErrorHandling(options.headerSchema ?? zJwtHeader, headerJson) as InferSchemaOutput<
const header = parseWithErrorHandling(options.headerSchema ?? zJwtHeader, headerJson) as InferSchemaOrDefaultOutput<
HeaderSchema,
typeof zJwtHeader
>
Expand Down
12 changes: 6 additions & 6 deletions packages/oauth2/src/common/jwt/decode-jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ export type DecodeJwtResult<
HeaderSchema extends BaseSchema | undefined = undefined,
PayloadSchema extends BaseSchema | undefined = undefined,
> = {
header: InferSchemaOutput<HeaderSchema, typeof zJwtHeader>
payload: InferSchemaOutput<PayloadSchema, typeof zJwtPayload>
header: InferSchemaOrDefaultOutput<HeaderSchema, typeof zJwtHeader>
payload: InferSchemaOrDefaultOutput<PayloadSchema, typeof zJwtPayload>
signature: string
}

Expand All @@ -56,15 +56,15 @@ export function decodeJwt<
'Unable to parse jwt payload to JSON'
)
} catch (error) {
throw new Oauth2JwtParseError('Error parsing JWT')
throw new Oauth2JwtParseError(`Error parsing JWT. ${error instanceof Error ? error.message : ''}`)
}

const { header } = decodeJwtHeader({ jwt: options.jwt, headerSchema: options.headerSchema })
const payload = parseWithErrorHandling(options.payloadSchema ?? zJwtPayload, payloadJson)

return {
header: header as InferSchemaOutput<HeaderSchema, typeof zJwtHeader>,
payload: payload as InferSchemaOutput<PayloadSchema, typeof zJwtPayload>,
header: header as InferSchemaOrDefaultOutput<HeaderSchema, typeof zJwtHeader>,
payload: payload as InferSchemaOrDefaultOutput<PayloadSchema, typeof zJwtPayload>,
signature: jwtParts[2],
}
}
Expand Down Expand Up @@ -169,7 +169,7 @@ export function jwtSignerFromJwt({ header, payload }: Pick<DecodeJwtResult, 'hea
type IsSchemaProvided<T> = T extends undefined ? false : true

// Helper type to infer the output type based on whether a schema is provided
export type InferSchemaOutput<
export type InferSchemaOrDefaultOutput<
ProvidedSchema extends BaseSchema | undefined,
DefaultSchema extends BaseSchema,
> = IsSchemaProvided<ProvidedSchema> extends true
Expand Down
13 changes: 13 additions & 0 deletions packages/oauth2/src/common/jwt/verify-jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ export interface VerifyJwtOptions {
* Expected value for the 'sub' claim
*/
expectedSubject?: string

/**
* The claims that are required to be present in the jwt.
*/
requiredClaims?: string[]
}

export interface VerifyJwtReturn {
Expand Down Expand Up @@ -127,6 +132,14 @@ export async function verifyJwt(options: VerifyJwtOptions): Promise<VerifyJwtRet
throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'sub' does not match expected value.`)
}

if (options.requiredClaims) {
for (const claim of options.requiredClaims) {
if (!options.payload[claim]) {
throw new Oauth2JwtVerificationError(`${errorMessage} jwt '${claim}' is missing.`)
}
}
}

return {
signer: {
...options.signer,
Expand Down
8 changes: 8 additions & 0 deletions packages/oauth2/src/common/z-oauth2-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ export enum Oauth2ErrorCodes {
InvalidRequestObject = 'invalid_request_object',
RequestNotSupported = 'request_not_supported',
RequestUriNotSupported = 'request_uri_not_supported',

// OpenId4Vp
VpFormatsNotSupported = 'vp_formats_not_supported',
InvalidPresentationDefinitionUri = 'invalid_presentation_definition_uri',
InvalidPresentationDefinitionReference = 'invalid_presentation_definition_reference',
InvalidRequestUriMethod = 'invalid_request_uri_method',
InvalidTransactionData = 'invalid_transaction_data',
WalletUnavailable = 'wallet_unavailable',
}

export const zOauth2ErrorResponse = z
Expand Down
4 changes: 3 additions & 1 deletion packages/oauth2/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,6 @@ export {
export { JwtHeader, JwtPayload } from './common/jwt/z-jwt'
export { verifyJwt } from './common/jwt/verify-jwt'
export { zJwkSet } from './common/jwk/z-jwk'
export { decodeJwtHeader } from './common/jwt/decode-jwt-header'
export { decodeJwtHeader, DecodeJwtHeaderResult } from './common/jwt/decode-jwt-header'

export { zAlgValueNotNone } from './common/z-common'
2 changes: 1 addition & 1 deletion packages/oid4vci/src/Oid4vciClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export interface Oid4vciClientOptions {
/**
* Callbacks required for the oid4vc client
*/
callbacks: Omit<CallbackContext, 'verifyJwt' | 'clientAuthentication' | 'decryptJwt' | 'encryptJwe'>
callbacks: Omit<CallbackContext, 'verifyJwt' | 'clientAuthentication' | 'decryptJwe' | 'encryptJwe'>
}

export class Oid4vciClient {
Expand Down
2 changes: 1 addition & 1 deletion packages/oid4vci/src/Oid4vciIssuer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export interface Oid4vciIssuerOptions {
/**
* Callbacks required for the oid4vc issuer
*/
callbacks: Omit<CallbackContext, 'decryptJwt' | 'encryptJwe'>
callbacks: Omit<CallbackContext, 'decryptJwe' | 'encryptJwe'>
}

export class Oid4vciIssuer {
Expand Down
61 changes: 61 additions & 0 deletions packages/openid4vp/src/Oid4vcVerifier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import type { CallbackContext } from '@openid4vc/oauth2'
import {
type CreateOpenid4vpAuthorizationRequestOptions,
createOpenid4vpAuthorizationRequest,
} from './authorization-request/create-authorization-request'
import {
type ParseOpenid4vpAuthRequestPayloadOptions,
parseOpenid4vpAuthorizationRequestPayload,
} from './authorization-request/parse-authorization-request-params'
import {} from './authorization-request/resolve-authorization-request'
import {
type ParseOpenid4vpAuthorizationResponseOptions,
parseOpenid4vpAuthorizationResponse,
} from './authorization-response/parse-authorization-response'
import {
type ValidateOpenid4vpAuthorizationResponseOptions,
validateOpenid4vpAuthorizationResponse,
} from './authorization-response/validate-authorization-response'
import type { ParseTransactionDataOptions } from './transaction-data/parse-transaction-data'
import { parseTransactionData } from './transaction-data/parse-transaction-data'
import {
type ParsePresentationsFromVpTokenOptions,
parsePresentationsFromVpToken,
} from './vp-token/parse-presentations-from-vp-token'

export interface Oid4vciVerifierOptions {
/**
* Callbacks required for the oid4vc issuer
*/
callbacks: Omit<CallbackContext, 'hash' | 'generateRandom' | 'clientAuthentication'>
}

export class Oid4vcVerifier {
public constructor(private options: Oid4vciVerifierOptions) {}

public async createOpenId4vpAuthorizationRequest(
options: Omit<CreateOpenid4vpAuthorizationRequestOptions, 'callbacks'>
) {
return createOpenid4vpAuthorizationRequest({ ...options, callbacks: this.options.callbacks })
}

public parseOpenid4vpAuthorizationRequestPayload(options: ParseOpenid4vpAuthRequestPayloadOptions) {
return parseOpenid4vpAuthorizationRequestPayload(options)
}

public parseOpenid4vpAuthorizationResponse(options: ParseOpenid4vpAuthorizationResponseOptions) {
return parseOpenid4vpAuthorizationResponse(options)
}

public validateOpenid4vpAuthorizationResponse(options: ValidateOpenid4vpAuthorizationResponseOptions) {
return validateOpenid4vpAuthorizationResponse(options)
}

public parsePresentationsFromVpToken(options: ParsePresentationsFromVpTokenOptions) {
return parsePresentationsFromVpToken(options)
}

public parseTransactionData(options: ParseTransactionDataOptions) {
return parseTransactionData(options)
}
}
49 changes: 49 additions & 0 deletions packages/openid4vp/src/Oid4vpClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import type { CallbackContext } from '@openid4vc/oauth2'
import {} from './authorization-request/create-authorization-request'
import { parseOpenid4vpAuthorizationRequestPayload } from './authorization-request/parse-authorization-request-params'
import type { ParseOpenid4vpAuthRequestPayloadOptions } from './authorization-request/parse-authorization-request-params'
import {
type ResolveOpenid4vpAuthorizationRequestOptions,
resolveOpenid4vpAuthorizationRequest,
} from './authorization-request/resolve-authorization-request'
import {
type CreateOpenid4vpAuthorizationResponseOptions,
createOpenid4vpAuthorizationResponse,
} from './authorization-response/create-authorization-response'
import {
type SubmitOpenid4vpAuthorizationResponseOptions,
submitOpenid4vpAuthorizationResponse,
} from './authorization-response/submit-authorization-response'

export interface Oid4vciClientOptions {
/**
* Callbacks required for the oid4vc issuer
*/
callbacks: Omit<CallbackContext, 'hash' | 'generateRandom' | 'clientAuthentication'>
}

export class Oid4vpClient {
public constructor(private options: Oid4vciClientOptions) {}

public parseOpenid4vpAuthorizationRequestPayload(options: ParseOpenid4vpAuthRequestPayloadOptions) {
return parseOpenid4vpAuthorizationRequestPayload(options)
}

public async resolveOpenId4vpAuthorizationRequest(
options: Omit<ResolveOpenid4vpAuthorizationRequestOptions, 'callbacks'>
) {
return resolveOpenid4vpAuthorizationRequest({ ...options, callbacks: this.options.callbacks })
}

public async createOpenid4vpAuthorizationResponse(
options: Omit<CreateOpenid4vpAuthorizationResponseOptions, 'callbacks'>
) {
return createOpenid4vpAuthorizationResponse({ ...options, callbacks: this.options.callbacks })
}

public async submitOpenid4vpAuthorizationResponse(
options: Omit<SubmitOpenid4vpAuthorizationResponseOptions, 'callbacks'>
) {
return submitOpenid4vpAuthorizationResponse({ ...options, callbacks: this.options.callbacks })
}
}
Loading

0 comments on commit 84a8dec

Please sign in to comment.