Skip to content

Commit

Permalink
chore: Added additional tests including http(s) urls
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoë Maas committed May 6, 2024
1 parent 968cc5f commit 4eaa40a
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 8 deletions.
20 changes: 20 additions & 0 deletions packages/client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ client you can use to finish the pre-authorized code flows.
This initiates the client using a URI obtained from the Issuer using a link (URL) or QR code typically. We are also
already fetching the Server Metadata


Using openid-initiate-issuance scheme
```typescript
import { OpenID4VCIClient } from '@sphereon/oid4vci-client';

Expand All @@ -68,6 +70,24 @@ console.log(client.getCredentialEndpoint()); // https://issuer.research.identipr
console.log(client.getAccessTokenEndpoint()); // https://auth.research.identiproof.io/oauth2/token
```

Using https scheme
```typescript
import { OpenID4VCIClient } from '@sphereon/oid4vci-client';

// The client is initiated from a URI. This URI is provided by the Issuer, typically as a URL or QR code.
const client = await OpenID4VCIClient.fromURI({
uri: 'https://launchpad.vii.electron.mattrlabs.io?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Flaunchpad.vii.electron.mattrlabs.io%22%2C%22credentials%22%3A%5B%7B%22format%22%3A%22ldp_vc%22%2C%22types%22%3A%5B%22OpenBadgeCredential%22%5D%7D%5D%2C%22grants%22%3A%7B%22urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Apre-authorized_code%22%3A%7B%22pre-authorized_code%22%3A%22UPZohaodPlLBnGsqB02n2tIupCIg8nKRRUEUHWA665X%22%7D%7D%7D',
kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21#key-1', // Our DID. You can defer this also to when the acquireCredential method is called
alg: Alg.ES256, // The signing Algorithm we will use. You can defer this also to when the acquireCredential method is called
clientId: 'test-clientId', // The clientId if the Authrozation Service requires it. If a clientId is needed you can defer this also to when the acquireAccessToken method is called
retrieveServerMetadata: true, // Already retrieve the server metadata. Can also be done afterwards by invoking a method yourself.
});

console.log(client.getIssuer()); // https://launchpad.vii.electron.mattrlabs.io
console.log(client.getCredentialEndpoint()); // https://launchpad.vii.electron.mattrlabs.io/credential
console.log(client.getAccessTokenEndpoint()); // https://launchpad.vii.electron.mattrlabs.io/oauth2/token
```

## Server metadata

The OID4VCI Server metadata contains information about token endpoints, credential endpoints, as well as additional
Expand Down
27 changes: 25 additions & 2 deletions packages/client/lib/__tests__/IT.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ describe('OID4VCI-Client should', () => {
const INITIATE_QR =
'openid-initiate-issuance://?issuer=https%3A%2F%2Fissuer.research.identiproof.io&credential_type=OpenBadgeCredentialUrl&pre-authorized_code=4jLs9xZHEfqcoow0kHE7d1a8hUk6Sy-5bVSV2MqBUGUgiFFQi-ImL62T-FmLIo8hKA1UdMPH0lM1xAgcFkJfxIw9L-lI3mVs0hRT8YVwsEM1ma6N3wzuCdwtMU4bcwKp&user_pin_required=true';
const OFFER_QR =
'openid-credential-offer://credential_offer=%7B%22credential_issuer%22:%22https://credential-issuer.example.com%22,%22credentials%22:%5B%7B%22format%22:%22jwt_vc_json%22,%22types%22:%5B%22VerifiableCredential%22,%22UniversityDegreeCredential%22%5D%7D%5D,%22issuer_state%22:%22eyJhbGciOiJSU0Et...FYUaBy%22%7D';
'openid-credential-offer://credential_offer=%7B%22credential_issuer%22:%22https://issuer.research.identiproof.io%22,%22credentials%22:%5B%7B%22format%22:%22jwt_vc_json%22,%22types%22:%5B%22VerifiableCredential%22,%22UniversityDegreeCredential%22%5D%7D%5D,%22issuer_state%22:%22eyJhbGciOiJSU0Et...FYUaBy%22%7D';
const HTTPS = 'https://issuer.research.identiproof.io?issuer=https%3A%2F%2Fissuer.research.identiproof.io&credential_type=OpenBadgeCredentialUrl&pre-authorized_code=4jLs9xZHEfqcoow0kHE7d1a8hUk6Sy-5bVSV2MqBUGUgiFFQi-ImL62T-FmLIo8hKA1UdMPH0lM1xAgcFkJfxIw9L-lI3mVs0hRT8YVwsEM1ma6N3wzuCdwtMU4bcwKp&user_pin_required=true'

function succeedWithAFullFlowWithClientSetup() {
nock(IDENTIPROOF_ISSUER_URL).get('/.well-known/openid-credential-issuer').reply(200, JSON.stringify(IDENTIPROOF_OID4VCI_METADATA));
Expand Down Expand Up @@ -78,7 +79,7 @@ describe('OID4VCI-Client should', () => {
await assertionOfsucceedWithAFullFlowWithClient(client);
});

test.skip('succeed with a full flow wit the client using OpenID4VCI version 11', async () => {
test.skip('succeed with a full flow with the client using OpenID4VCI version 11 and deeplink', async () => {
succeedWithAFullFlowWithClientSetup();
const client = await OpenID4VCIClient.fromURI({
uri: OFFER_QR,
Expand All @@ -89,6 +90,28 @@ describe('OID4VCI-Client should', () => {
await assertionOfsucceedWithAFullFlowWithClient(client);
});

/*
openid-initiate-issuance://?issuer=https://issuer.research.identiproof.io&credential_type=OpenBadgeCredentialUrl&pre-authorized_code=4jLs9xZHEfqcoow0kHE7d1a8hUk6Sy-5bVSV2MqBUGUgiFFQi-ImL62T-FmLIo8hKA1UdMPH0lM1xAgcFkJfxIw9L-lI3mVs0hRT8YVwsEM1ma6N3wzuCdwtMU4bcwKp&user_pin_required=true
####################################################################################################################################
openid-credential-offer://credential_offer={"credential_issuer":"https://issuer.research.identiproof.io","credentials":[{"format":"jwt_vc_json","types":["VerifiableCredential","UniversityDegreeCredential"]}],"issuer_state":"eyJhbGciOiJSU0Et...FYUaBy"}
####################################################################################################################################
https://issuer.research.identiproof.io?issuer=https://issuer.research.identiproof.io&credential_type=OpenBadgeCredentialUrl&pre-authorized_code=4jLs9xZHEfqcoow0kHE7d1a8hUk6Sy-5bVSV2MqBUGUgiFFQi-ImL62T-FmLIo8hKA1UdMPH0lM1xAgcFkJfxIw9L-lI3mVs0hRT8YVwsEM1ma6N3wzuCdwtMU4bcwKp&user_pin_required=true
*/
it('succeed with a full flow with the client using OpenID4VCI version 11 and https', async () => {
succeedWithAFullFlowWithClientSetup()
const client = await OpenID4VCIClient.fromURI({
uri: HTTPS,
kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1',
alg: Alg.ES256,
clientId: 'test-clientId'
})
await assertionOfsucceedWithAFullFlowWithClient(client);
})

async function assertionOfsucceedWithAFullFlowWithClient(client: OpenID4VCIClient) {
expect(client.credentialOffer).toBeDefined();
expect(client.endpointMetadata).toBeDefined();
Expand Down
12 changes: 6 additions & 6 deletions packages/client/lib/__tests__/IssuanceInitiation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,23 +61,23 @@ describe('Issuance Initiation', () => {

it('Should take an https url as input and return a Credential Offer', async () => {
const client = await CredentialOfferClient.fromURI(
'https://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Flaunchpad.vii.electron.mattrlabs.io%22%2C%22credentials%22%3A%5B%7B%22format%22%3A%22ldp_vc%22%2C%22types%22%3A%5B%22OpenBadgeCredential%22%5D%7D%5D%2C%22grants%22%3A%7B%22urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Apre-authorized_code%22%3A%7B%22pre-authorized_code%22%3A%22UPZohaodPlLBnGsqB02n2tIupCIg8nKRRUEUHWA665X%22%7D%7D%7D',
'https://launchpad.vii.electron.mattrlabs.io?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Flaunchpad.vii.electron.mattrlabs.io%22%2C%22credentials%22%3A%5B%7B%22format%22%3A%22ldp_vc%22%2C%22types%22%3A%5B%22OpenBadgeCredential%22%5D%7D%5D%2C%22grants%22%3A%7B%22urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Apre-authorized_code%22%3A%7B%22pre-authorized_code%22%3A%22UPZohaodPlLBnGsqB02n2tIupCIg8nKRRUEUHWA665X%22%7D%7D%7D',
);
expect(client.version).toEqual(OpenId4VCIVersion.VER_1_0_11);
expect(client.baseUrl).toEqual('https://');
expect(client.baseUrl).toEqual('https://launchpad.vii.electron.mattrlabs.io');
expect(client.scheme).toEqual('https');
expect(client.credential_offer.credential_issuer).toEqual('https://launchpad.vii.electron.mattrlabs.io');
expect(client.preAuthorizedCode).toEqual('UPZohaodPlLBnGsqB02n2tIupCIg8nKRRUEUHWA665X');
})

it('Should take an https url as input and return a Credential Offer', async () => {
it('Should take an http url as input and return a Credential Offer', async () => {
const client = await CredentialOfferClient.fromURI(
'http://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Flaunchpad.vii.electron.mattrlabs.io%22%2C%22credentials%22%3A%5B%7B%22format%22%3A%22ldp_vc%22%2C%22types%22%3A%5B%22OpenBadgeCredential%22%5D%7D%5D%2C%22grants%22%3A%7B%22urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Apre-authorized_code%22%3A%7B%22pre-authorized_code%22%3A%22UPZohaodPlLBnGsqB02n2tIupCIg8nKRRUEUHWA665X%22%7D%7D%7D',
'http://launchpad.vii.electron.mattrlabs.io?credential_offer=%7B%22credential_issuer%22%3A%22http%3A%2F%2Flaunchpad.vii.electron.mattrlabs.io%22%2C%22credentials%22%3A%5B%7B%22format%22%3A%22ldp_vc%22%2C%22types%22%3A%5B%22OpenBadgeCredential%22%5D%7D%5D%2C%22grants%22%3A%7B%22urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Apre-authorized_code%22%3A%7B%22pre-authorized_code%22%3A%22UPZohaodPlLBnGsqB02n2tIupCIg8nKRRUEUHWA665X%22%7D%7D%7D',
);
expect(client.version).toEqual(OpenId4VCIVersion.VER_1_0_11);
expect(client.baseUrl).toEqual('http://');
expect(client.baseUrl).toEqual('http://launchpad.vii.electron.mattrlabs.io');
expect(client.scheme).toEqual('http');
expect(client.credential_offer.credential_issuer).toEqual('https://launchpad.vii.electron.mattrlabs.io');
expect(client.credential_offer.credential_issuer).toEqual('http://launchpad.vii.electron.mattrlabs.io');
expect(client.preAuthorizedCode).toEqual('UPZohaodPlLBnGsqB02n2tIupCIg8nKRRUEUHWA665X');
})
});
56 changes: 56 additions & 0 deletions packages/issuer/lib/__tests__/CredentialOfferUtils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,60 @@ describe('CredentialOfferUtils should', () => {
'openid-credential-offer://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Fcredential-issuer.example.com%22%2C%22credentials%22%3A%5B%7B%22format%22%3A%22jwt_vc_json%22%2C%22types%22%3A%5B%22VerifiableCredential%22%2C%22UniversityDegreeCredential%22%5D%7D%5D%2C%22grants%22%3A%7B%22authorization_code%22%3A%7B%22issuer_state%22%3A%22eyJhbGciOiJSU0Et...FYUaBy%22%7D%7D%7D',
)
})

it('create an https link from credentialOffer object', () => {
// below is the example from spec (https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0-11.html#name-sending-credential-offer-by) and is wrong, the issuer_state should be in the grants and not a top-level property
// https://credential-issuer.example.com?credential_offer=%7B%22credential_issuer%22:%22https://credential-issuer.example.com%22,%22credentials%22:%5B%7B%22format%22:%22jwt_vc_json%22,%22types%22:%5B%22VerifiableCredential%22,%22UniversityDegreeCredential%22%5D%7D%5D,%22issuer_state%22:%22eyJhbGciOiJSU0Et...FYUaBy%22%7D
const credentialOffer = {
credential_issuer: 'https://credential-issuer.example.com',
credentials: [
{
format: 'jwt_vc_json',
types: ['VerifiableCredential', 'UniversityDegreeCredential'],
},
],
grants: {
authorization_code: {
issuer_state: 'eyJhbGciOiJSU0Et...FYUaBy',
},
},
} as CredentialOfferPayloadV1_0_11

expect(createCredentialOfferURI({
credential_issuer: credentialOffer.credential_issuer,
credential_endpoint: 'test_issuer',
issuer: 'test_issuer',
credentials_supported: []
}, { credentialOffer, state: 'eyJhbGciOiJSU0Et...FYUaBy', scheme: 'https' })).toEqual(
`${credentialOffer.credential_issuer}?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Fcredential-issuer.example.com%22%2C%22credentials%22%3A%5B%7B%22format%22%3A%22jwt_vc_json%22%2C%22types%22%3A%5B%22VerifiableCredential%22%2C%22UniversityDegreeCredential%22%5D%7D%5D%2C%22grants%22%3A%7B%22authorization_code%22%3A%7B%22issuer_state%22%3A%22eyJhbGciOiJSU0Et...FYUaBy%22%7D%7D%7D`,
)
})

it('create an http link from credentialOffer object', () => {
// below is the example from spec (https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0-11.html#name-sending-credential-offer-by) and is wrong, the issuer_state should be in the grants and not a top-level property
// http://credential-issuer.example.com?credential_offer=%7B%22credential_issuer%22:%22http://credential-issuer.example.com%22,%22credentials%22:%5B%7B%22format%22:%22jwt_vc_json%22,%22types%22:%5B%22VerifiableCredential%22,%22UniversityDegreeCredential%22%5D%7D%5D,%22issuer_state%22:%22eyJhbGciOiJSU0Et...FYUaBy%22%7D
const credentialOffer = {
credential_issuer: 'http://credential-issuer.example.com',
credentials: [
{
format: 'jwt_vc_json',
types: ['VerifiableCredential', 'UniversityDegreeCredential'],
},
],
grants: {
authorization_code: {
issuer_state: 'eyJhbGciOiJSU0Et...FYUaBy',
},
},
} as CredentialOfferPayloadV1_0_11

expect(createCredentialOfferURI({
credential_issuer: credentialOffer.credential_issuer,
credential_endpoint: 'test_issuer',
issuer: 'test_issuer',
credentials_supported: []
}, { credentialOffer, state: 'eyJhbGciOiJSU0Et...FYUaBy', scheme: 'http' })).toEqual(
`${credentialOffer.credential_issuer}?credential_offer=%7B%22credential_issuer%22%3A%22http%3A%2F%2Fcredential-issuer.example.com%22%2C%22credentials%22%3A%5B%7B%22format%22%3A%22jwt_vc_json%22%2C%22types%22%3A%5B%22VerifiableCredential%22%2C%22UniversityDegreeCredential%22%5D%7D%5D%2C%22grants%22%3A%7B%22authorization_code%22%3A%7B%22issuer_state%22%3A%22eyJhbGciOiJSU0Et...FYUaBy%22%7D%7D%7D`,
)
})
})

0 comments on commit 4eaa40a

Please sign in to comment.