Skip to content

Commit

Permalink
feat: Add supported flow type detection
Browse files Browse the repository at this point in the history
  • Loading branch information
nklomp committed May 28, 2023
1 parent 5cab075 commit 100f9e6
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 11 deletions.
2 changes: 1 addition & 1 deletion packages/client/lib/CredentialOfferClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Debug from 'debug';

import { convertJsonToURI, convertURIToJsonObject } from './functions';

const debug = Debug('sphereon:openid4vci:initiation');
const debug = Debug('sphereon:oid4vci:offer');

export class CredentialOfferClient {
public static async fromURI(uri: string, opts?: { resolve?: boolean }): Promise<CredentialOfferRequestWithBaseUrl> {
Expand Down
2 changes: 1 addition & 1 deletion packages/client/lib/CredentialRequestClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { CredentialRequestClientBuilder } from './CredentialRequestClientBuilder
import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder';
import { isValidURL, post } from './functions';

const debug = Debug('sphereon:openid4vci:credential');
const debug = Debug('sphereon:oid4vci:credential');

export interface CredentialRequestOpts {
credentialEndpoint: string;
Expand Down
2 changes: 1 addition & 1 deletion packages/client/lib/MetadataClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Debug from 'debug';

import { getJson } from './functions';

const debug = Debug('sphereon:openid4vci:metadata');
const debug = Debug('sphereon:oid4vci:metadata');

export class MetadataClient {
/**
Expand Down
15 changes: 11 additions & 4 deletions packages/client/lib/OpenID4VCIClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ export class OpenID4VCIClient {
alg?: Alg | string,
clientId?: string
) {
if (!credentialOffer.supportedFlows.includes(flowType)) {
throw Error(`Flows ${flowType} is not supported by issuer ${credentialOffer.credential_offer_uri}`);
}
this._flowType = flowType;
this._credentialOffer = credentialOffer;
this._kid = kid;
Expand Down Expand Up @@ -322,7 +325,7 @@ export class OpenID4VCIClient {
.withAlg(this.alg)
.withKid(this.kid);

if (this._clientId) {
if (this.clientId) {
proofBuilder.withClientId(this.clientId);
}
if (jti) {
Expand Down Expand Up @@ -413,6 +416,10 @@ export class OpenID4VCIClient {
return this._flowType;
}

issuerSupportedFlowTypes(): AuthzFlowType[] {
return this.credentialOffer.supportedFlows;
}

get credentialOffer(): CredentialOfferRequestWithBaseUrl {
return this._credentialOffer;
}
Expand Down Expand Up @@ -443,10 +450,10 @@ export class OpenID4VCIClient {
return this._alg;
}

get clientId(): string {
if (!this._clientId) {
get clientId(): string | undefined {
/*if (!this._clientId) {
throw Error('No client id present');
}
}*/
return this._clientId;
}

Expand Down
3 changes: 3 additions & 0 deletions packages/client/lib/__tests__/IssuanceInitiation.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { AuthzFlowType } from '@sphereon/oid4vci-common';

import { CredentialOfferClient } from '../CredentialOfferClient';

import { INITIATION_TEST, INITIATION_TEST_HTTPS_URI, INITIATION_TEST_URI } from './MetadataMocks';
Expand All @@ -21,6 +23,7 @@ describe('Issuance Initiation', () => {
op_state: 'eyJhbGciOiJSU0Et...FYUaBy',
},
scheme: 'https',
supportedFlows: [AuthzFlowType.AUTHORIZATION_CODE_FLOW],
version: 1008,
});
});
Expand Down
3 changes: 2 additions & 1 deletion packages/client/lib/__tests__/MetadataMocks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CredentialOfferPayloadV1_0_08, CredentialOfferRequestWithBaseUrl, OpenId4VCIVersion } from '@sphereon/oid4vci-common';
import { AuthzFlowType, CredentialOfferPayloadV1_0_08, CredentialOfferRequestWithBaseUrl, OpenId4VCIVersion } from '@sphereon/oid4vci-common';

export const IDENTIPROOF_ISSUER_URL = 'https://issuer.research.identiproof.io';
export const IDENTIPROOF_AS_URL = 'https://auth.research.identiproof.io';
Expand Down Expand Up @@ -31,6 +31,7 @@ export const INITIATION_TEST: CredentialOfferRequestWithBaseUrl = {
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhOTUyZjUxNi1jYWVmLTQ4YjMtODIxYy00OTRkYzgyNjljZjAiLCJwcmUtYXV0aG9yaXplZCI6dHJ1ZX0.YE5DlalcLC2ChGEg47CQDaN1gTxbaQqSclIVqsSAUHE',
user_pin_required: 'false',
} as CredentialOfferPayloadV1_0_08,
supportedFlows: [AuthzFlowType.PRE_AUTHORIZED_CODE_FLOW],
version: OpenId4VCIVersion.VER_1_0_08,
};
export const IDENTIPROOF_AS_METADATA = {
Expand Down
30 changes: 29 additions & 1 deletion packages/common/lib/functions/CredentialOfferUtil.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
AssertedUniformCredentialOffer,
AuthzFlowType,
CredentialOffer,
CredentialOfferPayload,
CredentialOfferPayloadV1_0_08,
Expand Down Expand Up @@ -154,10 +155,13 @@ export async function toUniformCredentialOfferRequest(
if (!originalCredentialOffer) {
throw Error('No credential offer available');
}
const payload = toUniformCredentialOfferPayload(originalCredentialOffer, opts);
const supportedFlows = determineFlowType(payload, version);
return {
credential_offer: toUniformCredentialOfferPayload(originalCredentialOffer, opts),
credential_offer: payload,
original_credential_offer: originalCredentialOffer,
...(credentialOfferURI && { credential_offer_uri: credentialOfferURI }),
supportedFlows,
version,
};
}
Expand Down Expand Up @@ -256,6 +260,30 @@ export function toUniformCredentialOfferPayload(
throw Error(`Could not create uniform payload for version ${version}`);
}

export function determineFlowType(
suppliedOffer: AssertedUniformCredentialOffer | UniformCredentialOfferPayload,
version: OpenId4VCIVersion
): AuthzFlowType[] {
let payload: UniformCredentialOfferPayload;
if ('credential_offer' in suppliedOffer && suppliedOffer['credential_offer']) {
payload = suppliedOffer.credential_offer;
} else {
payload = suppliedOffer as UniformCredentialOfferPayload;
}
const supportedFlows: AuthzFlowType[] = [];
if (payload.grants?.authorization_code) {
supportedFlows.push(AuthzFlowType.AUTHORIZATION_CODE_FLOW);
}
if (payload.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.['pre-authorized_code']) {
supportedFlows.push(AuthzFlowType.PRE_AUTHORIZED_CODE_FLOW);
}
if (supportedFlows.length === 0 && version < OpenId4VCIVersion.VER_1_0_09) {
// auth flow without op_state was possible in v08. The only way to know is that the detections would result in finding nothing.
supportedFlows.push(AuthzFlowType.AUTHORIZATION_CODE_FLOW);
}
return supportedFlows;
}

function getVersionFromURIParam(credentialOfferURI: string, currentVersion: OpenId4VCIVersion, matchingVersion: OpenId4VCIVersion, param: string) {
if (credentialOfferURI.includes(param)) {
return recordVersion(currentVersion, matchingVersion, param);
Expand Down
4 changes: 2 additions & 2 deletions packages/common/lib/types/CredentialIssuance.types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { W3CVerifiableCredential } from '@sphereon/ssi-types';

import { AuthzFlowType } from './Authorization.types';
import { OID4VCICredentialFormat } from './Generic.types';
import { OpenId4VCIVersion } from './OpenID4VCIVersions.types';
import { CredentialOfferPayloadV1_0_08 } from './v1_0_08.types';
Expand All @@ -17,8 +18,6 @@ export interface CredentialResponse {
export interface CredentialOfferRequestWithBaseUrl extends UniformCredentialOfferRequest {
scheme: string;
baseUrl: string;
/* request: CredentialOfferPayload;
version: OpenId4VCIVersion;*/
}

export type CredentialOffer = CredentialOfferV1_0_09 | CredentialOfferV1_0_11;
Expand All @@ -37,6 +36,7 @@ export interface UniformCredentialOffer {
export interface UniformCredentialOfferRequest extends AssertedUniformCredentialOffer {
original_credential_offer: CredentialOfferPayload;
version: OpenId4VCIVersion;
supportedFlows: AuthzFlowType[];
}

export type UniformCredentialOfferPayload = CredentialOfferPayloadV1_0_11;
Expand Down
1 change: 1 addition & 0 deletions packages/issuer-rest/lib/__tests__/ClientIssuerIT.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ describe('VcIssuer', () => {
},
},
scheme: 'http',
supportedFlows: [AuthzFlowType.AUTHORIZATION_CODE_FLOW, AuthzFlowType.PRE_AUTHORIZED_CODE_FLOW],
version: 1011,
})
expect(client.getIssuer()).toEqual(ISSUER_URL)
Expand Down
1 change: 1 addition & 0 deletions packages/issuer/lib/__tests__/VcIssuer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ describe('VcIssuer', () => {
},
},
scheme: 'http',
supportedFlows: [AuthzFlowType.AUTHORIZATION_CODE_FLOW, AuthzFlowType.PRE_AUTHORIZED_CODE_FLOW],
version: 1011,
})
})
Expand Down

0 comments on commit 100f9e6

Please sign in to comment.