Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/chubby-roses-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@openid4vc/openid4vci": minor
"@openid4vc/openid4vp": minor
"@openid4vc/oauth2": minor
"@openid4vc/utils": minor
---

chore: update to zod 4. Although the public API has not changed, it does impact the error messages and some of the error structures
4 changes: 2 additions & 2 deletions packages/oauth2/src/access-token/z-access-token-jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const zAccessTokenProfileJwtHeader = z
...zJwtHeader.shape,
typ: z.enum(['application/at+jwt', 'at+jwt']),
})
.passthrough()
.loose()
export type AccessTokenProfileJwtHeader = z.infer<typeof zAccessTokenProfileJwtHeader>

export const zAccessTokenProfileJwtPayload = z
Expand All @@ -26,6 +26,6 @@ export const zAccessTokenProfileJwtPayload = z
// SHOULD be included in the authorization request contained it
scope: z.optional(z.string()),
})
.passthrough()
.loose()

export type AccessTokenProfileJwtPayload = z.infer<typeof zAccessTokenProfileJwtPayload>
10 changes: 5 additions & 5 deletions packages/oauth2/src/access-token/z-access-token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const zAccessTokenRequest = z.intersection(

// Authorization code flow
code: z.optional(z.string()),
redirect_uri: z.string().url().optional(),
redirect_uri: z.url().optional(),

// Refresh token grant
refresh_token: z.optional(z.string()),
Expand All @@ -31,14 +31,14 @@ export const zAccessTokenRequest = z.intersection(
z.string(),
]),
})
.passthrough(),
.loose(),
z
.object({
tx_code: z.optional(z.string()),
// user_pin is from OpenID4VCI draft 11
user_pin: z.optional(z.string()),
})
.passthrough()
.loose()
.refine(({ tx_code, user_pin }) => !tx_code || !user_pin || user_pin === tx_code, {
message: `If both 'tx_code' and 'user_pin' are present they must match`,
})
Expand Down Expand Up @@ -74,11 +74,11 @@ export const zAccessTokenResponse = z
// required when type is openid_credential (so we probably need a discriminator)
// credential_identifiers: z.array(z.string()),
})
.passthrough()
.loose()
)
.optional(),
})
.passthrough()
.loose()

export type AccessTokenResponse = z.infer<typeof zAccessTokenResponse>

Expand Down
4 changes: 2 additions & 2 deletions packages/oauth2/src/access-token/z-token-introspection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const zTokenIntrospectionRequest = z
token: z.string(),
token_type_hint: z.optional(z.string()),
})
.passthrough()
.loose()

export type TokenIntrospectionRequest = z.infer<typeof zTokenIntrospectionRequest>

Expand All @@ -31,6 +31,6 @@ export const zTokenIntrospectionResponse = z

cnf: z.optional(zJwtConfirmationPayload),
})
.passthrough()
.loose()

export type TokenIntrospectionResponse = z.infer<typeof zTokenIntrospectionResponse>
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ export const zAuthorizationChallengeRequest = z
// DRAFT presentation during issuance
presentation_during_issuance_session: z.optional(z.string()),
})
.passthrough()
.loose()
export type AuthorizationChallengeRequest = z.infer<typeof zAuthorizationChallengeRequest>

export const zAuthorizationChallengeResponse = z
.object({
authorization_code: z.string(),
})
.passthrough()
.loose()
export type AuthorizationChallengeResponse = z.infer<typeof zAuthorizationChallengeResponse>

export const zAuthorizationChallengeErrorResponse = z
Expand All @@ -37,5 +37,5 @@ export const zAuthorizationChallengeErrorResponse = z
// DRAFT: presentation during issuance
presentation: z.optional(z.string()),
})
.passthrough()
.loose()
export type AuthorizationChallengeErrorResponse = z.infer<typeof zAuthorizationChallengeErrorResponse>
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,33 @@ export const zAuthorizationRequest = z
client_id: z.string(),

issuer_state: z.optional(z.string()),
redirect_uri: z.string().url().optional(),
redirect_uri: z.url().optional(),
resource: z.optional(zHttpsUrl),
scope: z.optional(z.string()),

// DPoP jwk thumbprint
dpop_jkt: z.optional(z.string().base64url()),
dpop_jkt: z.optional(z.base64url()),

code_challenge: z.optional(z.string()),
code_challenge_method: z.optional(z.string()),
})
.passthrough()
.loose()
export type AuthorizationRequest = z.infer<typeof zAuthorizationRequest>

export const zPushedAuthorizationRequest = z
.object({
request_uri: z.string(),
client_id: z.string(),
})
.passthrough()
.loose()
export type PushedAuthorizationRequest = z.infer<typeof zPushedAuthorizationRequest>

export const zPushedAuthorizationResponse = z
.object({
request_uri: z.string(),
expires_in: z.number().int(),
})
.passthrough()
.loose()
export type PushedAuthorizationResponse = z.infer<typeof zPushedAuthorizationResponse>

export const zPushedAuthorizationErrorResponse = zOauth2ErrorResponse
Expand Down
12 changes: 6 additions & 6 deletions packages/oauth2/src/client-attestation/z-client-attestation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ export const zClientAttestationJwtPayload = z
.object({
jwk: zJwk,
})
.passthrough(),
.loose(),

// OID4VCI Wallet Attestation Extensions
wallet_name: z.string().optional(),
wallet_link: z.string().url().optional(),
wallet_link: z.url().optional(),
})
.passthrough()
.loose()
export type ClientAttestationJwtPayload = z.infer<typeof zClientAttestationJwtPayload>

export const zClientAttestationJwtHeader = z
.object({
...zJwtHeader.shape,
typ: z.literal('oauth-client-attestation+jwt'),
})
.passthrough()
.loose()

export type ClientAttestationJwtHeader = z.infer<typeof zClientAttestationJwtHeader>

Expand All @@ -47,13 +47,13 @@ export const zClientAttestationPopJwtPayload = z
jti: z.string(),
nonce: z.optional(z.string()),
})
.passthrough()
.loose()
export type ClientAttestationPopJwtPayload = z.infer<typeof zClientAttestationPopJwtPayload>

export const zClientAttestationPopJwtHeader = z
.object({
...zJwtHeader.shape,
typ: z.literal('oauth-client-attestation-pop+jwt'),
})
.passthrough()
.loose()
export type ClientAttestationPopJwtHeader = z.infer<typeof zClientAttestationPopJwtHeader>
6 changes: 3 additions & 3 deletions packages/oauth2/src/common/jwk/z-jwk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const zJwk = z
r: z.optional(z.string()),
t: z.optional(z.string()),
})
.passthrough()
.loose()
)
),
p: z.optional(z.string()),
Expand All @@ -36,10 +36,10 @@ export const zJwk = z
'x5t#S256': z.optional(z.string()),
x5u: z.optional(z.string()),
})
.passthrough()
.loose()

export type Jwk = z.infer<typeof zJwk>

export const zJwkSet = z.object({ keys: z.array(zJwk) }).passthrough()
export const zJwkSet = z.object({ keys: z.array(zJwk) }).loose()

export type JwkSet = z.infer<typeof zJwkSet>
10 changes: 5 additions & 5 deletions packages/oauth2/src/common/jwt/z-jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export const zJwtConfirmationPayload = z
// RFC9449. jwk thumbprint of the dpop public key to which the access token is bound
jkt: z.string().optional(),
})
.passthrough()
.loose()

export const zJwtPayload = z
.object({
Expand All @@ -112,9 +112,9 @@ export const zJwtPayload = z
status: z.record(z.string(), z.any()).optional(),

// Reserved for OpenID Federation
trust_chain: z.array(z.string()).nonempty().optional(),
trust_chain: z.tuple([z.string()], z.string()).optional(),
})
.passthrough()
.loose()

export type JwtPayload = z.infer<typeof zJwtPayload>

Expand All @@ -128,8 +128,8 @@ export const zJwtHeader = z
x5c: z.array(z.string()).optional(),

// Reserved for OpenID Federation
trust_chain: z.array(z.string()).nonempty().optional(),
trust_chain: z.tuple([z.string()], z.string()).optional(),
})
.passthrough()
.loose()

export type JwtHeader = z.infer<typeof zJwtHeader>
4 changes: 2 additions & 2 deletions packages/oauth2/src/common/z-oauth2-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ export enum Oauth2ErrorCodes {

export const zOauth2ErrorResponse = z
.object({
error: z.union([z.nativeEnum(Oauth2ErrorCodes), z.string()]),
error: z.union([z.enum(Oauth2ErrorCodes), z.string()]),
error_description: z.string().optional(),
error_uri: z.string().optional(),
})
.passthrough()
.loose()

export type Oauth2ErrorResponse = z.infer<typeof zOauth2ErrorResponse>
4 changes: 2 additions & 2 deletions packages/oauth2/src/dpop/z-dpop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const zDpopJwtPayload = z
// Only required when presenting in combination with access token
ath: z.optional(z.string()),
})
.passthrough()
.loose()
export type DpopJwtPayload = z.infer<typeof zDpopJwtPayload>

export const zDpopJwtHeader = z
Expand All @@ -23,5 +23,5 @@ export const zDpopJwtHeader = z
typ: z.literal('dpop+jwt'),
jwk: zJwk,
})
.passthrough()
.loose()
export type DpopJwtHeader = z.infer<typeof zDpopJwtHeader>
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const zAuthorizationServerMetadata = z
// Attestation Based Client Auth (draft 5)
client_attestation_pop_nonce_required: z.boolean().optional(),
})
.passthrough()
.loose()
.refine(
({
introspection_endpoint_auth_methods_supported: methodsSupported,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ describe('Credential Offer', () => {
})

expect(parseResult.success).toBe(false)
expect(parseResult.error?.errors).toMatchInlineSnapshot(`
expect(parseResult.error?.issues).toMatchInlineSnapshot(`
[
{
"code": "invalid_type",
Expand All @@ -105,7 +105,6 @@ describe('Credential Offer', () => {
"credentials",
0,
],
"received": "object",
},
]
`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export async function resolveCredentialOffer(
): Promise<CredentialOfferObject> {
const parsedQueryParams = getQueryParams(credentialOffer)

let credentialOfferParseResult: z.SafeParseReturnType<unknown, z.infer<typeof zCredentialOfferObject>>
let credentialOfferParseResult: z.ZodSafeParseResult<z.infer<typeof zCredentialOfferObject>>

if (parsedQueryParams.credential_offer_uri) {
const fetchWithZod = createZodFetcher(options?.fetch)
Expand Down
14 changes: 7 additions & 7 deletions packages/openid4vci/src/credential-offer/z-credential-offer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const zTxCode = z
length: z.number().int().optional(),
description: z.string().max(300).optional(),
})
.passthrough()
.loose()

export type CredentialOfferPreAuthorizedCodeGrantTxCode = z.input<typeof zTxCode>

Expand All @@ -23,18 +23,18 @@ export const zCredentialOfferGrants = z
issuer_state: z.string().optional(),
authorization_server: zHttpsUrl.optional(),
})
.passthrough()
.loose()
.optional(),
[preAuthorizedCodeGrantIdentifier]: z
.object({
'pre-authorized_code': z.string(),
tx_code: zTxCode.optional(),
authorization_server: zHttpsUrl.optional(),
})
.passthrough()
.loose()
.optional(),
})
.passthrough()
.loose()

export type CredentialOfferGrants = z.input<typeof zCredentialOfferGrants>

Expand All @@ -47,7 +47,7 @@ const zCredentialOfferObjectDraft14 = z
credential_configuration_ids: z.array(z.string()),
grants: z.optional(zCredentialOfferGrants),
})
.passthrough()
.loose()
export type CredentialOfferObject = z.input<typeof zCredentialOfferObjectDraft14>

export const zCredentialOfferObjectDraft11To14 = z
Expand All @@ -67,12 +67,12 @@ export const zCredentialOfferObjectDraft11To14 = z
'pre-authorized_code': z.string(),
user_pin_required: z.optional(z.boolean()),
})
.passthrough()
.loose()
.optional(),
})
),
})
.passthrough()
.loose()
.transform(({ credentials, grants, ...rest }) => {
const v14: CredentialOfferObject = {
...rest,
Expand Down
Loading