Skip to content

Commit 5c5b3aa

Browse files
authored
Merge pull request #181 from Sphereon-Opensource/develop
New release
2 parents 7d93832 + 290b043 commit 5c5b3aa

190 files changed

Lines changed: 20425 additions & 10964 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build-test-on-pr.yml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ jobs:
2323
uses: actions/setup-node@v4
2424
with:
2525
node-version: '20.x'
26-
- uses: pnpm/action-setup@v3
26+
- uses: pnpm/action-setup@v4
2727
with:
28-
version: 8.15.7
28+
version: 9.15.3 # TODO remove later, we are temporary dealing with a broken pnpm version in the CI container
2929
- run: pnpm install
3030
- run: pnpm build
3131
- name: run CI tests
@@ -41,4 +41,13 @@ jobs:
4141
SPHEREON_SSI_MSAL_USERNAME: ${{ secrets.SPHEREON_SSI_MSAL_USERNAME }}
4242
SPHEREON_SSI_MSAL_PASSWORD: ${{ secrets.SPHEREON_SSI_MSAL_PASSWORD }}
4343
run: pnpm test:ci
44-
- run: npx codecov
44+
- name: codecov
45+
uses: codecov/codecov-action@v4
46+
with:
47+
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
48+
name: codecove # optional
49+
flags: unittest
50+
fail_ci_if_error: true # optional (default = false)
51+
#directory: ./coverage/reports/
52+
#files: ./coverage1.xml,./coverage2.xml
53+
verbose: true # optional (default = false)

.github/workflows/build-test-publish-on-push.yml

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,9 @@ jobs:
3737
uses: actions/setup-node@v4
3838
with:
3939
node-version: '20.x'
40-
- uses: pnpm/action-setup@v3
40+
- uses: pnpm/action-setup@v4
4141
with:
42-
version: 8.15.7
43-
# - name: Get yarn cache directory path
44-
# id: yarn-cache-dir-path
45-
# run: echo "::set-output name=dir::$(yarn cache dir)"
46-
# - uses: actions/cache@v2
47-
# id: yarn-cache
48-
# with:
49-
# path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
50-
# key: ${{ runner.os }}-yarn-2-${{ hashFiles('**/package.json') }}
51-
42+
version: 9.15.3 # TODO remove later, we are temporary dealing with a broken pnpm version in the CI container
5243
- run: pnpm install
5344
- run: pnpm build
5445
- name: run integration tests
@@ -81,18 +72,25 @@ jobs:
8172
- name: diff
8273
run: git diff
8374

75+
- name: Sets PREID
76+
env:
77+
name: "${{github.ref_name}}"
78+
run: |
79+
echo "PRE_ID=${name//[\/_-]/.}" >> $GITHUB_ENV
80+
8481
- name: publish @latest when on main
8582
if: github.ref == 'refs/heads/main'
86-
run: pnpm publish:latest
83+
run: lerna publish --conventional-commits --force-publish --include-merged-tags --sync-dist-version --create-release github --yes --dist-tag latest --registry https://registry.npmjs.org
8784

8885
- name: publish @next when on develop
8986
if: github.ref == 'refs/heads/develop'
90-
run: pnpm publish:next
87+
run: lerna publish --conventional-prerelease --force-publish --canary --sync-dist-version --no-git-tag-version --include-merged-tags --preid next --pre-dist-tag next --yes --registry https://registry.npmjs.org
9188

92-
- name: publish @next when on fix
89+
- name: publish @next when on fix branch
9390
if: startsWith(github.ref, 'refs/heads/fix')
94-
run: pnpm publish:next
91+
run: lerna publish --conventional-prerelease --force-publish --canary --sync-dist-version --no-git-tag-version --include-merged-tags --preid fix --pre-dist-tag fix --yes --registry https://registry.npmjs.org
9592

9693
- name: publish @unstable when on unstable branch
9794
if: startsWith(github.ref, 'refs/heads/feat')
98-
run: pnpm publish:unstable
95+
run: lerna publish --conventional-prerelease --force-publish --canary --sync-dist-version --no-git-tag-version --include-merged-tags --preid $PRE_ID --pre-dist-tag unstable --yes --throttle-size 75 --registry https://registry.npmjs.org
96+

package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
"node": ">=18"
2424
},
2525
"resolutions": {
26+
"@sphereon/ssi-types": "^0.32.1-next.161",
27+
"dcql": "0.2.19",
2628
"node-fetch": "2.6.12"
2729
},
2830
"prettier": {
@@ -35,7 +37,6 @@
3537
"@types/debug": "^4.1.12",
3638
"@types/jest": "^29.5.12",
3739
"@types/node": "^18.19.39",
38-
"codecov": "^3.8.3",
3940
"jest": "^29.7.0",
4041
"lerna": "^8.1.6",
4142
"lerna-changelog": "^2.2.0",
@@ -48,10 +49,13 @@
4849
"keywords": [
4950
"Sphereon",
5051
"Verifiable Credentials",
52+
"ARF",
53+
"EUIDW",
5154
"OpenID",
5255
"SIOP",
56+
"SIOPv2",
5357
"Self Issued OpenID Provider",
54-
"OPenId for Verifiable Presentations",
58+
"OpenId for Verifiable Presentations",
5559
"OpenID for Verifiable Credential Issuance",
5660
"OAuth2",
5761
"SSI",

packages/callback-example/lib/__tests__/issuerCallback.spec.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
CNonceState,
88
CredentialConfigurationSupportedV1_0_13,
99
CredentialIssuerMetadataV1_0_13,
10+
CredentialOfferSession,
1011
CredentialRequest,
1112
IssuerCredentialSubjectDisplay,
1213
IssueStatus,
@@ -15,9 +16,13 @@ import {
1516
OpenId4VCIVersion,
1617
ProofOfPossession,
1718
} from '@sphereon/oid4vci-common'
18-
import { CredentialOfferSession } from '@sphereon/oid4vci-common/dist'
19-
import { CredentialSupportedBuilderV1_13, VcIssuer, VcIssuerBuilder } from '@sphereon/oid4vci-issuer'
20-
import { MemoryStates } from '@sphereon/oid4vci-issuer'
19+
import {
20+
AuthorizationServerMetadataBuilder,
21+
CredentialSupportedBuilderV1_13,
22+
MemoryStates,
23+
VcIssuer,
24+
VcIssuerBuilder,
25+
} from '@sphereon/oid4vci-issuer'
2126
import { CredentialDataSupplierResult } from '@sphereon/oid4vci-issuer/dist/types'
2227
import { ICredential, IProofPurpose, IProofType, W3CVerifiableCredential } from '@sphereon/ssi-types'
2328
import { DIDDocument } from 'did-resolver'
@@ -47,7 +52,17 @@ async function proofOfPossessionCallbackFunction(args: Jwt, kid?: string): Promi
4752
.sign(keypair.privateKey)
4853
}
4954

50-
async function verifyCallbackFunction(args: { jwt: string; kid?: string }): Promise<JwtVerifyResult<DIDDocument>> {
55+
const authorizationServerMetadata = new AuthorizationServerMetadataBuilder()
56+
.withIssuer(IDENTIPROOF_ISSUER_URL)
57+
.withCredentialEndpoint('http://localhost:3456/test/credential-endpoint')
58+
.withTokenEndpoint('http://localhost:3456/test/token')
59+
.withAuthorizationEndpoint('https://token-endpoint.example.com/authorize')
60+
.withTokenEndpointAuthMethodsSupported(['none', 'client_secret_basic', 'client_secret_jwt', 'client_secret_post'])
61+
.withResponseTypesSupported(['code', 'token', 'id_token'])
62+
.withScopesSupported(['openid', 'abcdef'])
63+
.build()
64+
65+
async function verifyCallbackFunction(args: { jwt: string; kid?: string }): Promise<JwtVerifyResult> {
5166
const result = await jose.jwtVerify(args.jwt, keypair.publicKey)
5267
const kid = result.protectedHeader.kid ?? args.kid
5368
const did = kid!.split('#')[0]
@@ -83,7 +98,7 @@ afterAll(async () => {
8398
await new Promise((resolve) => setTimeout((v: void) => resolve(v), 500))
8499
})
85100
describe('issuerCallback', () => {
86-
let vcIssuer: VcIssuer<DIDDocument>
101+
let vcIssuer: VcIssuer
87102
const state = 'existing-state'
88103
const clientId = 'sphereon:wallet'
89104

@@ -146,10 +161,11 @@ describe('issuerCallback', () => {
146161

147162
const nonces = new MemoryStates<CNonceState>()
148163
await nonces.set('test_value', { cNonce: 'test_value', createdAt: +new Date(), issuerState: 'existing-state' })
149-
vcIssuer = new VcIssuerBuilder<DIDDocument>()
164+
vcIssuer = new VcIssuerBuilder()
150165
.withAuthorizationServers('https://authorization-server')
151166
.withCredentialEndpoint('https://credential-endpoint')
152167
.withCredentialIssuer(IDENTIPROOF_ISSUER_URL)
168+
.withAuthorizationMetadata(authorizationServerMetadata)
153169
.withIssuerDisplay({
154170
name: 'example issuer',
155171
locale: 'en-US',

packages/callback-example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"@sphereon/oid4vci-client": "workspace:*",
2020
"@sphereon/oid4vci-common": "workspace:*",
2121
"@sphereon/oid4vci-issuer": "workspace:*",
22-
"@sphereon/ssi-types": "0.28.0",
22+
"@sphereon/ssi-types": "^0.32.1-next.161",
2323
"jose": "^4.10.0"
2424
},
2525
"devDependencies": {

packages/client/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ console.log(accessToken);
110110
/**
111111
* {
112112
* access_token: 'ey6546.546654.64565',
113-
* authorization_pending: false,
114113
* c_nonce: 'c_nonce2022101300',
115114
* c_nonce_expires_in: 2025101300,
116115
* interval: 2025101300,

packages/client/lib/AccessTokenClient.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export class AccessTokenClient {
116116

117117
return {
118118
...response,
119-
params: { ...(nextDPoPNonce && { dpop: { dpopNonce: nextDPoPNonce } }) },
119+
...(nextDPoPNonce && { params: { dpop: { dpopNonce: nextDPoPNonce } } }),
120120
};
121121
}
122122

@@ -132,18 +132,7 @@ export class AccessTokenClient {
132132
const credentialIssuer = opts.credentialIssuer ?? credentialOfferRequest?.credential_offer?.credential_issuer ?? opts.metadata?.issuer;
133133
await createJwtBearerClientAssertion(request, { ...opts, credentialIssuer });
134134

135-
if (credentialOfferRequest?.supportedFlows.includes(AuthzFlowType.PRE_AUTHORIZED_CODE_FLOW)) {
136-
this.assertAlphanumericPin(opts.pinMetadata, pin);
137-
request.user_pin = pin;
138-
request.tx_code = pin;
139-
140-
request.grant_type = GrantTypes.PRE_AUTHORIZED_CODE;
141-
// we actually know it is there because of the isPreAuthCode call
142-
request[PRE_AUTH_CODE_LITERAL] = credentialOfferRequest?.credential_offer.grants?.[PRE_AUTH_GRANT_LITERAL]?.[PRE_AUTH_CODE_LITERAL];
143-
144-
return request as AccessTokenRequest;
145-
}
146-
135+
// Prefer AUTHORIZATION_CODE over PRE_AUTHORIZED_CODE_FLOW
147136
if (!credentialOfferRequest || credentialOfferRequest.supportedFlows.includes(AuthzFlowType.AUTHORIZATION_CODE_FLOW)) {
148137
request.grant_type = GrantTypes.AUTHORIZATION_CODE;
149138
request.code = code;
@@ -156,6 +145,18 @@ export class AccessTokenClient {
156145
return request as AccessTokenRequest;
157146
}
158147

148+
if (credentialOfferRequest?.supportedFlows.includes(AuthzFlowType.PRE_AUTHORIZED_CODE_FLOW)) {
149+
this.assertAlphanumericPin(opts.pinMetadata, pin);
150+
request.user_pin = pin;
151+
request.tx_code = pin;
152+
153+
request.grant_type = GrantTypes.PRE_AUTHORIZED_CODE;
154+
// we actually know it is there because of the isPreAuthCode call
155+
request[PRE_AUTH_CODE_LITERAL] = credentialOfferRequest?.credential_offer.grants?.[PRE_AUTH_GRANT_LITERAL]?.[PRE_AUTH_CODE_LITERAL];
156+
157+
return request as AccessTokenRequest;
158+
}
159+
159160
throw new Error('Credential offer request follows neither pre-authorized code nor authorization code flow requirements.');
160161
}
161162

@@ -238,6 +239,7 @@ export class AccessTokenClient {
238239
throw new Error('Authorization flow requires the code to be present');
239240
}
240241
}
242+
241243
private validate(accessTokenRequest: AccessTokenRequest, pinMeta?: TxCodeAndPinRequired): void {
242244
if (accessTokenRequest.grant_type === GrantTypes.PRE_AUTHORIZED_CODE) {
243245
this.assertPreAuthorizedGrantType(accessTokenRequest.grant_type);

packages/client/lib/AccessTokenClientV1_0_11.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export class AccessTokenClientV1_0_11 {
120120

121121
return {
122122
...response,
123-
params: { ...(nextDPoPNonce && { dpop: { dpopNonce: nextDPoPNonce } }) },
123+
...(nextDPoPNonce && { params: { dpop: { dpopNonce: nextDPoPNonce } } }),
124124
};
125125
}
126126

@@ -137,17 +137,7 @@ export class AccessTokenClientV1_0_11 {
137137
}
138138
await createJwtBearerClientAssertion(request, { ...opts, version: OpenId4VCIVersion.VER_1_0_11, credentialIssuer });
139139

140-
if (credentialOfferRequest?.supportedFlows.includes(AuthzFlowType.PRE_AUTHORIZED_CODE_FLOW)) {
141-
this.assertNumericPin(this.isPinRequiredValue(credentialOfferRequest.credential_offer), pin);
142-
request.user_pin = pin;
143-
144-
request.grant_type = GrantTypes.PRE_AUTHORIZED_CODE;
145-
// we actually know it is there because of the isPreAuthCode call
146-
request[PRE_AUTH_CODE_LITERAL] = credentialOfferRequest?.credential_offer.grants?.[PRE_AUTH_GRANT_LITERAL]?.[PRE_AUTH_CODE_LITERAL];
147-
148-
return request as AccessTokenRequest;
149-
}
150-
140+
// Prefer AUTHORIZATION_CODE over PRE_AUTHORIZED_CODE_FLOW
151141
if (!credentialOfferRequest || credentialOfferRequest.supportedFlows.includes(AuthzFlowType.AUTHORIZATION_CODE_FLOW)) {
152142
request.grant_type = GrantTypes.AUTHORIZATION_CODE;
153143
request.code = code;
@@ -160,6 +150,16 @@ export class AccessTokenClientV1_0_11 {
160150
return request as AccessTokenRequest;
161151
}
162152

153+
if (credentialOfferRequest?.supportedFlows.includes(AuthzFlowType.PRE_AUTHORIZED_CODE_FLOW)) {
154+
this.assertNumericPin(this.isPinRequiredValue(credentialOfferRequest.credential_offer), pin);
155+
request.user_pin = pin;
156+
157+
request.grant_type = GrantTypes.PRE_AUTHORIZED_CODE;
158+
// we actually know it is there because of the isPreAuthCode call
159+
request[PRE_AUTH_CODE_LITERAL] = credentialOfferRequest?.credential_offer.grants?.[PRE_AUTH_GRANT_LITERAL]?.[PRE_AUTH_CODE_LITERAL];
160+
161+
return request as AccessTokenRequest;
162+
}
163163
throw new Error('Credential offer request does not follow neither pre-authorized code nor authorization code flow requirements.');
164164
}
165165

@@ -220,6 +220,7 @@ export class AccessTokenClientV1_0_11 {
220220
throw new Error('Authorization flow requires the code to be present');
221221
}
222222
}
223+
223224
private validate(accessTokenRequest: AccessTokenRequest, isPinRequired?: boolean): void {
224225
if (accessTokenRequest.grant_type === GrantTypes.PRE_AUTHORIZED_CODE) {
225226
this.assertPreAuthorizedGrantType(accessTokenRequest.grant_type);

0 commit comments

Comments
 (0)