Skip to content

Commit 17ec6b8

Browse files
feat!: auth code flow (openwallet-foundation#2088)
Signed-off-by: Timo Glastra <timo@animo.id> Co-authored-by: Martin Auer <martin.auer97@gmail.com>
1 parent 1e2271a commit 17ec6b8

99 files changed

Lines changed: 9533 additions & 4258 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.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@credo-ts/openid4vc': patch
3+
---
4+
5+
fix(openid4vc): use `vp_formats` in client_metadata instead of `vp_formats supported` (#2089)

.changeset/perfect-islands-grin.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@credo-ts/openid4vc': patch
3+
---
4+
5+
feat(openid4vc): support jwk thumbprint for openid token issuer

.changeset/shiny-sheep-appear.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
'@credo-ts/openid4vc': minor
3+
---
4+
5+
feat(openid4vc): oid4vci authorization code flow, presentation during issuance and batch issuance.
6+
7+
This is a big change to OpenID4VCI in Credo, with the neccsary breaking changes since we first added it to the framework. Over time the spec has changed significantly, but also our understanding of the standards and protocols.
8+
9+
**Authorization Code Flow**
10+
Credo now supports the authorization code flow, for both issuer and holder. An issuer can configure multiple authorization servers, and work with external authorization servers as well. The integration is based on OAuth2, with several extension specifications, mainly the OAuth2 JWT Access Token Profile, as well as Token Introspection (for opaque access tokens). Verification works out of the box, as longs as the authorization server has a `jwks_uri` configured. For Token Introspection it's also required to provide a `clientId` and `clientSecret` in the authorization server config.
11+
12+
To use an external authorization server, the authorization server MUST include the `issuer_state` parameter from the credential offer in the access token. Otherwise it's not possible for Credo to correlate the authorization session to the offer session.
13+
14+
The demo-openid contains an example with external authorization server, which can be used as reference. The Credo authorization server supports DPoP and PKCE.
15+
16+
**Batch Issuance**
17+
The credential request to credential mapper has been updated to support multiple proofs, and also multiple credential instances. The client can now also handle batch issuance.
18+
19+
**Presentation During Issuance**
20+
The presenation during issuance allows to request presentation using OID4VP before granting authorization for issuance of one or more credentials. This flow is automatically handled by the `resolveAuthorizationRequest` method on the oid4vci holder service.

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ module.exports = {
116116
'demo-openid/**',
117117
'scripts/**',
118118
'**/tests/**',
119+
'tests/**',
119120
],
120121
env: {
121122
jest: true,

.github/workflows/continuous-integration.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ jobs:
129129
- run: mv coverage/coverage-final.json coverage/${{ matrix.shard }}.json
130130
- uses: actions/upload-artifact@v4
131131
with:
132-
name: coverage-artifacts
132+
name: coverage-artifacts-${{ matrix.node-version }}
133133
path: coverage/${{ matrix.shard }}.json
134134
overwrite: true
135135

@@ -184,7 +184,7 @@ jobs:
184184
- run: mv coverage/coverage-final.json coverage/e2e.json
185185
- uses: actions/upload-artifact@v4
186186
with:
187-
name: coverage-artifacts
187+
name: coverage-artifacts-${{ matrix.node-version }}
188188
path: coverage/e2e.json
189189
overwrite: true
190190

@@ -195,9 +195,10 @@ jobs:
195195
steps:
196196
- uses: actions/download-artifact@v4
197197
with:
198-
name: coverage-artifacts
198+
name: coverage-artifacts-20
199199
path: coverage
200200

201201
- uses: codecov/codecov-action@v4
202202
with:
203203
directory: coverage
204+
token: ${{ secrets.CODECOV_TOKEN }}

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ aries-framework-*.tgz
99
coverage
1010
.DS_Store
1111
logs.txt
12-
logs/
12+
logs/
13+
14+
ngrok.auth.yml

demo-openid/README.md

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ Alice, a former student of Faber College, connects with the College, is issued a
66

77
## Features
88

9-
- ✅ Issuing a credential.
9+
- ✅ Issuing a credential without authorization (pre-authorized code flow).
10+
- ✅ Issuing a credenital with external authorization server (authorization code flow)
1011
- ✅ Resolving a credential offer.
1112
- ✅ Accepting a credential offer.
1213
- ✅ Requesting a credential presentation.
@@ -29,7 +30,7 @@ Clone the Credo git repository:
2930
git clone https://github.com/openwallet-foundation/credo-ts.git
3031
```
3132

32-
Open three different terminals next to each other and in both, go to the demo folder:
33+
Open four different terminals next to each other and in each, go to the demo folder:
3334

3435
```sh
3536
cd credo-ts/demo-openid
@@ -41,13 +42,19 @@ Install the project in one of the terminals:
4142
pnpm install
4243
```
4344

44-
In the first terminal run the Issuer:
45+
In the first terminal run the OpenID Provider:
46+
47+
```sh
48+
pnpm provider
49+
```
50+
51+
In the second terminal run the Issuer:
4552

4653
```sh
4754
pnpm issuer
4855
```
4956

50-
In the second terminal run the Holder:
57+
In the third terminal run the Holder:
5158

5259
```sh
5360
pnpm holder
@@ -65,7 +72,8 @@ To create a credential offer:
6572

6673
- Go to the Issuer terminal.
6774
- Select `Create a credential offer`.
68-
- Select `UniversityDegreeCredential`.
75+
- Choose whether authorization is required
76+
- Select the credential(s) you want to issue.
6977
- Now copy the content INSIDE the quotes (without the quotes).
7078

7179
To resolve and accept the credential:
@@ -74,6 +82,8 @@ To resolve and accept the credential:
7482
- Select `Resolve a credential offer`.
7583
- Paste the content copied from the credential offer and hit enter.
7684
- Select `Accept the credential offer`.
85+
- Choose which credential(s) to accept
86+
- If authorization is required a link will be printed in the terminal, open this in your browser. You can sign in using any username and password. Once authenticated return to the terminal
7787
- You have now stored your credential.
7888

7989
To create a presentation request:
@@ -99,3 +109,29 @@ Exit:
99109
Restart:
100110

101111
- Select 'restart', to shutdown the current program and start a new one
112+
113+
### Optional Proxy
114+
115+
By default all services will be started on `localhost`, and thus won't be reachable by other external services (such as a mobile wallet). If you want to expose the required services to the public, you need to expose multiple ngrok tunnels.
116+
117+
We can setup the tunnels automatically using ngrok. First make sure you have an ngrok account and get your access token from this page: https://dashboard.ngrok.com/get-started/setup/
118+
119+
Then copy the `ngrok.auth.example.yml` file to `ngrok.auth.yml`:
120+
121+
```sh
122+
cp ngrok.auth.example.yml ngrok.auth.yml
123+
```
124+
125+
And finally set the `authtoken` to the auth token as displayed in the ngrok dashboard.
126+
127+
Once set up, you can run the following command in a separate terminal window.
128+
129+
```sh
130+
pnpm proxies
131+
```
132+
133+
This will open three proxies. You should then run your demo environments with these proxies:
134+
135+
- `PROVIDER_HOST=https://d404-123-123-123-123.ngrok-free.app ISSUER_HOST=https://d738-123-123-123-123.ngrok-free.app pnpm provider` (ngrok url for port 3042)
136+
- `PROVIDER_HOST=https://d404-123-123-123-123.ngrok-free.app ISSUER_HOST=https://d738-123-123-123-123.ngrok-free.app pnpm issuer` (ngrok url for port 2000)
137+
- `VERIFIER_HOST=https://1d91-123-123-123-123.ngrok-free.app pnpm verifier` (ngrok url for port 4000)

demo-openid/ngrok.auth.example.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
authtoken: ea8af45e-0a76-44d5-b2a2-bab9d4bfb346
2+
version: '2'

demo-openid/ngrok.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
version: 2
2+
3+
tunnels:
4+
issuer:
5+
proto: http
6+
addr: 2000
7+
provider:
8+
proto: http
9+
addr: 3042
10+
verifier:
11+
proto: http
12+
addr: 4000

demo-openid/package.json

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,20 @@
1010
"license": "Apache-2.0",
1111
"scripts": {
1212
"issuer": "ts-node src/IssuerInquirer.ts",
13+
"provider": "tsx src/provider.js",
1314
"holder": "ts-node src/HolderInquirer.ts",
14-
"verifier": "ts-node src/VerifierInquirer.ts"
15+
"verifier": "ts-node src/VerifierInquirer.ts",
16+
"proxies": "ngrok --config ngrok.yml,ngrok.auth.yml start provider issuer verifier"
1517
},
1618
"dependencies": {
1719
"@hyperledger/anoncreds-nodejs": "^0.2.2",
1820
"@hyperledger/aries-askar-nodejs": "^0.2.3",
1921
"@hyperledger/indy-vdr-nodejs": "^0.2.2",
22+
"@koa/bodyparser": "^5.1.1",
2023
"express": "^4.18.1",
21-
"inquirer": "^8.2.5"
24+
"inquirer": "^8.2.5",
25+
"jose": "^5.3.0",
26+
"oidc-provider": "^8.4.6"
2227
},
2328
"devDependencies": {
2429
"@credo-ts/askar": "workspace:*",
@@ -28,8 +33,10 @@
2833
"@types/express": "^4.17.13",
2934
"@types/figlet": "^1.5.4",
3035
"@types/inquirer": "^8.2.6",
36+
"@types/oidc-provider": "^8.4.4",
3137
"clear": "^0.1.0",
3238
"figlet": "^1.5.2",
33-
"ts-node": "^10.9.2"
39+
"ts-node": "^10.9.2",
40+
"tsx": "^4.11.0"
3441
}
3542
}

0 commit comments

Comments
 (0)