Skip to content

Commit

Permalink
fix: (WIP) refactored and fixed build. still have to fix 33 test case…
Browse files Browse the repository at this point in the history
…s that are failing
  • Loading branch information
sksadjad committed May 10, 2024
1 parent bba1eed commit ff88a64
Show file tree
Hide file tree
Showing 47 changed files with 12,189 additions and 8,378 deletions.
53 changes: 27 additions & 26 deletions packages/callback-example/lib/__tests__/issuerCallback.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
ProofOfPossession,
} from '@sphereon/oid4vci-common'
import { CredentialOfferSession } from '@sphereon/oid4vci-common/dist'
import { CredentialSupportedBuilderV1_13, VcIssuer, VcIssuerBuilderV1_0_11 } from '@sphereon/oid4vci-issuer'
import { CredentialSupportedBuilderV1_13, VcIssuer, VcIssuerBuilder } from '@sphereon/oid4vci-issuer'
import { MemoryStates } from '@sphereon/oid4vci-issuer'
import { CredentialDataSupplierResult } from '@sphereon/oid4vci-issuer/dist/types'
import { ICredential, IProofPurpose, IProofType, W3CVerifiableCredential } from '@sphereon/ssi-types'
Expand All @@ -37,7 +37,7 @@ async function proofOfPossessionCallbackFunction(args: Jwt, kid?: string): Promi
}
return await new jose.SignJWT({ ...args.payload })
.setProtectedHeader({ ...args.header })
.setIssuedAt(args.payload.iat ?? Math.round(+new Date()/1000))
.setIssuedAt(args.payload.iat ?? Math.round(+new Date() / 1000))
.setIssuer(kid)
.setAudience(args.payload.aud)
.setExpirationTime('2h')
Expand Down Expand Up @@ -85,27 +85,28 @@ describe('issuerCallback', () => {
const clientId = 'sphereon:wallet'

beforeAll(async () => {
const credentialsSupported: CredentialConfigurationSupported = new CredentialSupportedBuilderV1_13()
.withCryptographicSuitesSupported('ES256K')
.withCryptographicBindingMethod('did')
.withFormat('jwt_vc_json')
.withTypes('VerifiableCredential')
.withId('UniversityDegree_JWT')
.withCredentialSupportedDisplay({
name: 'University Credential',
locale: 'en-US',
logo: {
url: 'https://exampleuniversity.com/public/logo.png',
alt_text: 'a square logo of a university',
},
background_color: '#12107c',
text_color: '#FFFFFF',
})
.addCredentialSubjectPropertyDisplay('given_name', {
name: 'given name',
locale: 'en-US',
} as IssuerCredentialSubjectDisplay)
.build()
const credentialsSupported: Record<string, CredentialConfigurationSupported> =
new CredentialSupportedBuilderV1_13()
.withCryptographicSuitesSupported('ES256K')
.withCryptographicBindingMethod('did')
.withFormat('jwt_vc_json')
.withTypes('VerifiableCredential')
.withId('UniversityDegree_JWT')
.withCredentialSupportedDisplay({
name: 'University Credential',
locale: 'en-US',
logo: {
url: 'https://exampleuniversity.com/public/logo.png',
alt_text: 'a square logo of a university',
},
background_color: '#12107c',
text_color: '#FFFFFF',
})
.addCredentialSubjectPropertyDisplay('given_name', {
name: 'given name',
locale: 'en-US',
} as IssuerCredentialSubjectDisplay)
.build()
const stateManager = new MemoryStates<CredentialOfferSession>()
await stateManager.set('existing-state', {
issuerState: 'existing-state',
Expand Down Expand Up @@ -140,15 +141,15 @@ describe('issuerCallback', () => {

const nonces = new MemoryStates<CNonceState>()
await nonces.set('test_value', { cNonce: 'test_value', createdAt: +new Date(), issuerState: 'existing-state' })
vcIssuer = new VcIssuerBuilderV1_0_11<DIDDocument>()
.withAuthorizationServer('https://authorization-server')
vcIssuer = new VcIssuerBuilder<DIDDocument>()
.withAuthorizationServers('https://authorization-server')
.withCredentialEndpoint('https://credential-endpoint')
.withCredentialIssuer(IDENTIPROOF_ISSUER_URL)
.withIssuerDisplay({
name: 'example issuer',
locale: 'en-US',
})
.withCredentialsSupported(credentialsSupported)
.withCredentialConfigurationsSupported(credentialsSupported)
.withCredentialOfferStateManager(stateManager)
.withCNonceStateManager(nonces)
.withJWTVerifyCallback(verifyCallbackFunction)
Expand Down
33 changes: 22 additions & 11 deletions packages/client/lib/AccessTokenClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@ import {
assertedUniformCredentialOffer,
AuthorizationServerOpts,
AuthzFlowType,
CredentialOfferPayloadV1_0_13,
CredentialOfferV1_0_13,
determineSpecVersionFromOffer,
EndpointMetadata,
getIssuerFromCredentialOfferPayload,
GrantTypes,
IssuerOpts,
JsonURIMode,
OpenId4VCIVersion,
OpenIDResponse,
PRE_AUTH_CODE_LITERAL,
TokenErrorResponse,
toUniformCredentialOfferRequest,
TxCode,
UniformCredentialOfferPayload,
} from '@sphereon/oid4vci-common';
import { ObjectUtils } from '@sphereon/ssi-types';
Expand All @@ -29,7 +34,8 @@ export class AccessTokenClient {
const { asOpts, pin, codeVerifier, code, redirectUri, metadata } = opts;

const credentialOffer = opts.credentialOffer ? await assertedUniformCredentialOffer(opts.credentialOffer) : undefined;
const isPinRequired = credentialOffer && this.isPinRequiredValue(credentialOffer.credential_offer);
const txCode: TxCode | undefined =
credentialOffer?.credential_offer.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.tx_code ?? undefined;
const issuer =
opts.credentialIssuer ??
(credentialOffer ? getIssuerFromCredentialOfferPayload(credentialOffer.credential_offer) : (metadata?.issuer as string));
Expand All @@ -48,8 +54,9 @@ export class AccessTokenClient {
code,
redirectUri,
pin,
txCode,
}),
isPinRequired,
txCode,
metadata,
asOpts,
issuerOpts,
Expand All @@ -58,18 +65,18 @@ export class AccessTokenClient {

public async acquireAccessTokenUsingRequest({
accessTokenRequest,
isPinRequired,
txCode,
metadata,
asOpts,
issuerOpts,
}: {
accessTokenRequest: AccessTokenRequest;
isPinRequired?: boolean;
txCode?: TxCode;
metadata?: EndpointMetadata;
asOpts?: AuthorizationServerOpts;
issuerOpts?: IssuerOpts;
}): Promise<OpenIDResponse<AccessTokenResponse>> {
this.validate(accessTokenRequest, isPinRequired);
this.validate(accessTokenRequest, txCode);

const requestTokenURL = AccessTokenClient.determineTokenURL({
asOpts,
Expand All @@ -86,7 +93,11 @@ export class AccessTokenClient {

public async createAccessTokenRequest(opts: AccessTokenRequestOpts): Promise<AccessTokenRequest> {
const { asOpts, pin, codeVerifier, code, redirectUri } = opts;
const credentialOfferRequest = opts.credentialOffer ? await toUniformCredentialOfferRequest(opts.credentialOffer) : undefined;
const credentialOfferRequest =
opts.credentialOffer &&
determineSpecVersionFromOffer(opts.credentialOffer as CredentialOfferPayloadV1_0_13).valueOf() <= OpenId4VCIVersion.VER_1_0_13.valueOf()
? await toUniformCredentialOfferRequest(opts.credentialOffer as CredentialOfferV1_0_13)
: undefined;
const request: Partial<AccessTokenRequest> = {};

if (asOpts?.clientId) {
Expand Down Expand Up @@ -138,14 +149,14 @@ export class AccessTokenClient {
throw new Error(TokenErrorResponse.invalid_request);
}
const issuer = getIssuerFromCredentialOfferPayload(requestPayload);
if (requestPayload.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']) {
isPinRequired = requestPayload.grants['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.user_pin_required ?? false;
if (requestPayload.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.tx_code) {
isPinRequired = true;
}
debug(`Pin required for issuer ${issuer}: ${isPinRequired}`);
return isPinRequired;
}

private assertNumericPin(isPinRequired?: boolean, pin?: string): void {
private assertNumericPin(isPinRequired: boolean, pin?: string): void {
if (isPinRequired) {
if (!pin || !/^\d{1,8}$/.test(pin)) {
debug(`Pin is not 1 to 8 digits long`);
Expand Down Expand Up @@ -177,11 +188,11 @@ export class AccessTokenClient {
throw new Error('Authorization flow requires the code to be present');
}
}
private validate(accessTokenRequest: AccessTokenRequest, isPinRequired?: boolean): void {
private validate(accessTokenRequest: AccessTokenRequest, txCode?: TxCode): void {
if (accessTokenRequest.grant_type === GrantTypes.PRE_AUTHORIZED_CODE) {
this.assertPreAuthorizedGrantType(accessTokenRequest.grant_type);
this.assertNonEmptyPreAuthorizedCode(accessTokenRequest);
this.assertNumericPin(isPinRequired, accessTokenRequest.user_pin);
this.assertNumericPin(!!txCode, accessTokenRequest.user_pin);
} else if (accessTokenRequest.grant_type === GrantTypes.AUTHORIZATION_CODE) {
this.assertAuthorizationGrantType(accessTokenRequest.grant_type);
this.assertNonEmptyCodeVerifier(accessTokenRequest);
Expand Down
Loading

0 comments on commit ff88a64

Please sign in to comment.