Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: openid4vc support #1667

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
7245031
fix: port openid4vci from paradym wallet
auer-martin Oct 9, 2023
36d417f
refactor: remove unused import
auer-martin Oct 10, 2023
fecbdc9
refactor: and add some TODOs
auer-martin Oct 10, 2023
feba10e
feat: crete openid4vc-holder package
auer-martin Oct 10, 2023
21bc559
feat: create issuer, holder and verifier pacakge
auer-martin Oct 10, 2023
93200ec
fix: package.json
auer-martin Oct 10, 2023
10e9bfa
fix: rename client to holder
auer-martin Oct 11, 2023
41c681e
feat: change the shape of the holder api
auer-martin Oct 16, 2023
e20fb7b
feat: add more info for credential selection
auer-martin Oct 16, 2023
71d1b73
fix: copy & paste error
auer-martin Oct 16, 2023
6e2cf46
feat: change public api and others
auer-martin Oct 18, 2023
8a79069
fix: remove some todos
auer-martin Oct 18, 2023
f7d7904
fix: remove credential metadata
auer-martin Oct 18, 2023
f2648b5
feat: make metadata optional
auer-martin Oct 18, 2023
791a06f
fix: tests
auer-martin Oct 18, 2023
fd87a82
fix: test
auer-martin Oct 19, 2023
aba5009
feat: add changes from paradym wallet
auer-martin Oct 23, 2023
8aafb5d
feat: authorization code flow (alpha)
auer-martin Oct 24, 2023
18f6d72
feat: authorization code flow
auer-martin Oct 25, 2023
60369ef
refactor: rename
auer-martin Oct 25, 2023
93d6219
refactor: restructure
auer-martin Oct 25, 2023
b07981a
refactor: imports
auer-martin Oct 25, 2023
3e7b162
refactor: restructure
auer-martin Oct 25, 2023
3bf4ff7
refactor: holder vci side
auer-martin Oct 26, 2023
8f07645
fix: format and tests
auer-martin Oct 26, 2023
082934b
refactor: issuermetadata
auer-martin Oct 26, 2023
3fcdd8b
refactor: restructure
auer-martin Oct 26, 2023
42d1801
fix: incorporate parts of the pr feedback
auer-martin Oct 31, 2023
3bef9c0
chore: incorporate feedback
auer-martin Nov 6, 2023
1bd0c65
chore: incorporate feedback
auer-martin Nov 7, 2023
ff1428b
chore: basic siop/vp support
auer-martin Nov 10, 2023
7319361
fix: do not throw if wrong or no crendentials are in wallet
auer-martin Nov 12, 2023
83325e1
fix: don't return empty presentation submission
auer-martin Nov 12, 2023
c21b063
test: remove old test
auer-martin Nov 12, 2023
0ec0832
refactor: rename variables and function
auer-martin Nov 12, 2023
1d1a752
test: expect submitting a wrong submission to fail
auer-martin Nov 12, 2023
3158f83
tests: add more test cases
auer-martin Nov 12, 2023
eb58ad9
fix: check VpFormat, fix test
auer-martin Nov 12, 2023
e1d6c70
fix: import statement in
auer-martin Nov 12, 2023
055605d
feat: create getProofTypeForLdpVc method and use Pex to create submis…
auer-martin Nov 13, 2023
6a3dd63
feat: add openid4vc issuer support
auer-martin Nov 15, 2023
f1919e2
fix: verifier remove duplicate
auer-martin Nov 15, 2023
d36cc27
reactor: verifier miscellaneous changes
auer-martin Nov 15, 2023
9459a04
reactor: holder miscellaneous changes
auer-martin Nov 15, 2023
8ecc486
fix: remove unnecessary dependencies
auer-martin Nov 15, 2023
f82a8f7
Merge branch 'openid4vc'
auer-martin Nov 15, 2023
fdff7b3
refactor: make type for auth req with code
auer-martin Nov 15, 2023
0c6d7bb
fix: package.json add askar and afj/node as dependency
auer-martin Nov 15, 2023
a717378
chore: fix universal resolver fallback. name param correctly, and rem…
auer-martin Nov 16, 2023
4c1d3a3
chore: miscellaneous refactorings
auer-martin Nov 16, 2023
5a3fd6c
fix: export all service options
auer-martin Nov 16, 2023
c9a0652
fix: miscellaneous
auer-martin Nov 16, 2023
ed47cdc
refactor: rename exports, change exports
auer-martin Nov 17, 2023
6e36e10
refactor: divide vci holder service and vp holder service
auer-martin Nov 17, 2023
648d59e
fix: package.json's and export presentation definition
auer-martin Nov 17, 2023
5aed962
fix: don't export authdetails
auer-martin Nov 20, 2023
668e24c
refactor: clean up some things
auer-martin Nov 20, 2023
bfb1720
refactor: rename presentations folder to presentation
auer-martin Nov 20, 2023
e1b6257
fix: authorization endpoint
auer-martin Nov 20, 2023
2bf9e4f
fix: AuthDetails not exported
auer-martin Nov 20, 2023
1be3576
refactor: module test names
auer-martin Nov 20, 2023
00a517d
test: add some tests for the verifier proof request
auer-martin Nov 20, 2023
6baf500
fix: export types and jwt_vc_json-ld
auer-martin Nov 20, 2023
7035265
fix: export types remove proofRequest type
auer-martin Nov 20, 2023
9b5dd42
fix: export types and move type definitions
auer-martin Nov 20, 2023
356497e
fix: remove and rename types
auer-martin Nov 20, 2023
7059dcb
fix: rename types, fix test, rename method
auer-martin Nov 20, 2023
5ce1794
fix: todos
auer-martin Nov 20, 2023
eb7884d
feat: restructure verifier, add verifier endpoint, add verifier sessi…
auer-martin Nov 22, 2023
f450617
feat: restructure issuance side
auer-martin Nov 22, 2023
9113461
refactor: rename file
auer-martin Nov 22, 2023
ee031ab
fix: remove duplicate
auer-martin Nov 22, 2023
903ecae
refactor: rename types and variables
auer-martin Nov 22, 2023
d517217
feat: add openid4vci endpoints
auer-martin Nov 23, 2023
21d265f
fix: consistency between issuer and verifier endpoints approach
auer-martin Nov 23, 2023
0711848
feat: add basic openid demo
auer-martin Nov 27, 2023
037e68c
feat: SdJwtVc issuance (hacky)
auer-martin Dec 1, 2023
f5f49ee
feat: add credential record migration
auer-martin Dec 4, 2023
5ff6e39
feat: wrap up sdjwtvc vci work part 1
auer-martin Dec 4, 2023
403176e
Merge branch 'main' into openid
auer-martin Dec 4, 2023
e685785
feat: remove sd-jwt-vc dependency
auer-martin Dec 5, 2023
34b39d8
feat: restructure openid4vc modules
auer-martin Dec 5, 2023
8a79da1
feat: multitenant support and refactorings
auer-martin Dec 8, 2023
eab4da8
fix: remove todos
auer-martin Dec 11, 2023
4e36a99
feat: ldp_vc proof requests
auer-martin Dec 14, 2023
3d9b842
fix: endpoints should not be absolute
auer-martin Dec 15, 2023
c7d9ba7
fix: migration
auer-martin Jan 4, 2024
4228f77
feat(tenants): expose additional record methods
TimoGlastra Jan 8, 2024
fd355cd
feat: add joinUriParts method
TimoGlastra Jan 8, 2024
2c94c61
feat(sd-jwt): update to latest version and improvementts
TimoGlastra Jan 8, 2024
9cbe491
type improvement
TimoGlastra Jan 8, 2024
106702a
sd jwt updates
TimoGlastra Jan 8, 2024
8acfb68
more sdjwt improvements
TimoGlastra Jan 10, 2024
d9896d7
typing improvements
TimoGlastra Jan 10, 2024
17a2d5c
oid4vc issuer record
TimoGlastra Jan 10, 2024
f140305
revamp issuer api
TimoGlastra Jan 10, 2024
82b53eb
issuance working
TimoGlastra Jan 11, 2024
e210e09
some additional updates
TimoGlastra Jan 12, 2024
3d5a75e
Merge remote-tracking branch 'upstream/main' into feat/openid4vc
TimoGlastra Jan 12, 2024
0217723
so much changes
TimoGlastra Jan 16, 2024
8afe0fd
dependency updates
TimoGlastra Jan 20, 2024
1f5729c
export type
TimoGlastra Jan 20, 2024
171a86d
some refactoring
TimoGlastra Jan 20, 2024
b74370b
refactored a bunch of code
TimoGlastra Jan 21, 2024
78dd60b
fix some issuer tests
TimoGlastra Jan 21, 2024
49d8a32
rework some tests
TimoGlastra Jan 21, 2024
590895c
expose signing methods on w3c service
TimoGlastra Jan 22, 2024
3c5f520
fix a bunch of tests
TimoGlastra Jan 22, 2024
54b3a17
add tags to sd-jwt record
TimoGlastra Jan 23, 2024
654bf1f
a lot of fixmes
TimoGlastra Jan 23, 2024
d7c64f0
chore: move sd-jwt-vc to core
TimoGlastra Jan 24, 2024
2ae6b32
a small bug
TimoGlastra Jan 24, 2024
de4e310
support sd-jwt in pex
TimoGlastra Jan 24, 2024
bdf2ca7
a lot of api updates
TimoGlastra Jan 25, 2024
f2ea107
some nice fixes
TimoGlastra Jan 28, 2024
6754b30
fixmes are fixed
TimoGlastra Jan 28, 2024
226de98
it actually compiles and runs!!
TimoGlastra Jan 28, 2024
b172c3d
eslint fixes
TimoGlastra Jan 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ module.exports = {
},
},
{
files: ['demo/**'],
files: ['demo/**', 'demo-openid/**'],
rules: {
'no-console': 'off',
},
Expand All @@ -112,6 +112,7 @@ module.exports = {
'jest.*.ts',
'samples/**',
'demo/**',
'demo-openid/**',
'scripts/**',
'**/tests/**',
],
Expand Down
89 changes: 89 additions & 0 deletions demo-openid/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<h1 align="center"><b>DEMO</b></h1>

This is the Aries Framework Javascript demo. Walk through the AFJ flow yourself together with agents Alice and Faber.

Alice, a former student of Faber College, connects with the College, is issued a credential about her degree and then is asked by the College for a proof.

## Features

- ✅ Creating a connection
- ✅ Offering a credential
- ✅ Requesting a proof
- ✅ Sending basic messages

## Getting Started

### Platform Specific Setup

In order to use Aries Framework JavaScript some platform specific dependencies and setup is required. See our guides below to quickly set up you project with Aries Framework JavaScript for NodeJS, React Native and Electron.

- [NodeJS](https://aries.js.org/guides/getting-started/installation/nodejs)

### Run the demo

These are the steps for running the AFJ demo:

Clone the AFJ git repository:

```sh
git clone https://github.com/hyperledger/aries-framework-javascript.git
```

Open two different terminals next to each other and in both, go to the demo folder:

```sh
cd aries-framework-javascript/demo
```

Install the project in one of the terminals:

```sh
yarn install
```

In the left terminal run Alice:

```sh
yarn alice
```

In the right terminal run Faber:

```sh
yarn faber
```

### Usage

To set up a connection:

- Select 'receive connection invitation' in Alice and 'create connection invitation' in Faber
- Faber will print a invitation link which you then copy and paste to Alice
- You have now set up a connection!

To offer a credential:

- Select 'offer credential' in Faber
- Faber will start with registering a schema and the credential definition accordingly
- You have now send a credential offer to Alice!
- Go to Alice to accept the incoming credential offer by selecting 'yes'.

To request a proof:

- Select 'request proof' in Faber
- Faber will create a new proof attribute and will then send a proof request to Alice!
- Go to Alice to accept the incoming proof request

To send a basic message:

- Select 'send message' in either one of the Agents
- Type your message and press enter
- Message sent!

Exit:

- Select 'exit' to shutdown the agent.

Restart:

- Select 'restart', to shutdown the current agent and start a new one
36 changes: 36 additions & 0 deletions demo-openid/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "afj-demo-openid",
"version": "1.0.0",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/hyperledger/aries-framework-javascript",
"directory": "demo-openid/"
},
"license": "Apache-2.0",
"scripts": {
"issuer": "ts-node src/IssuerInquirer.ts",
"holder": "ts-node src/HolderInquirer.ts",
"verifier": "ts-node src/VerifierInquirer.ts",
"refresh": "rm -rf ./node_modules ./yarn.lock && yarn"
},
"dependencies": {
"@aries-framework/openid4vc": "*",
"@hyperledger/anoncreds-nodejs": "^0.2.0-dev.4",
"@hyperledger/aries-askar-nodejs": "^0.2.0-dev.1",
"@hyperledger/indy-vdr-nodejs": "^0.2.0-dev.5",
"express": "^4.18.1",
"inquirer": "^8.2.5"
},
"devDependencies": {
"@aries-framework/askar": "*",
"@aries-framework/core": "*",
"@aries-framework/node": "*",
"@types/express": "^4.17.13",
"@types/figlet": "^1.5.4",
"@types/inquirer": "^8.2.6",
"clear": "^0.1.0",
"figlet": "^1.5.2",
"ts-node": "^10.4.0"
}
}
61 changes: 61 additions & 0 deletions demo-openid/src/BaseAgent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import type { InitConfig, KeyDidCreateOptions, ModulesMap, VerificationMethod } from '@aries-framework/core'
import type { Express } from 'express'

import { Agent, DidKey, HttpOutboundTransport, KeyType, TypedArrayEncoder } from '@aries-framework/core'
import { HttpInboundTransport, agentDependencies } from '@aries-framework/node'
import express from 'express'

import { greenText } from './OutputClass'

export class BaseAgent<AgentModules extends ModulesMap> {
public app: Express
public port: number
public name: string
public config: InitConfig
public agent: Agent<AgentModules>
public did!: string
public didKey!: DidKey
public kid!: string
public verificationMethod!: VerificationMethod

public constructor({ port, name, modules }: { port: number; name: string; modules: AgentModules }) {
this.name = name
this.port = port
this.app = express()

const config = {
label: name,
walletConfig: { id: name, key: name },
} satisfies InitConfig

this.config = config

this.agent = new Agent({ config, dependencies: agentDependencies, modules })

const httpInboundTransport = new HttpInboundTransport({ app: this.app, port: this.port })
const httpOutboundTransport = new HttpOutboundTransport()

this.agent.registerInboundTransport(httpInboundTransport)
this.agent.registerOutboundTransport(httpOutboundTransport)
}

public async initializeAgent(secretPrivateKey: string) {
await this.agent.initialize()

const didCreateResult = await this.agent.dids.create<KeyDidCreateOptions>({
method: 'key',
options: { keyType: KeyType.Ed25519 },
secret: { privateKey: TypedArrayEncoder.fromString(secretPrivateKey) },
})

this.did = didCreateResult.didState.did as string
this.didKey = DidKey.fromDid(this.did)
this.kid = `${this.did}#${this.didKey.key.fingerprint}`

const verificationMethod = didCreateResult.didState.didDocument?.dereferenceKey(this.kid, ['authentication'])
if (!verificationMethod) throw new Error('No verification method found')
this.verificationMethod = verificationMethod

console.log(greenText(`\nAgent ${this.name} created!\n`))
}
}
55 changes: 55 additions & 0 deletions demo-openid/src/BaseInquirer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { prompt } from 'inquirer'

import { Title } from './OutputClass'

export enum ConfirmOptions {
Yes = 'yes',
No = 'no',
}

export class BaseInquirer {
public optionsInquirer: { type: string; prefix: string; name: string; message: string; choices: string[] }
public inputInquirer: { type: string; prefix: string; name: string; message: string; choices: string[] }

public constructor() {
this.optionsInquirer = {
type: 'list',
prefix: '',
name: 'options',
message: '',
choices: [],
}

this.inputInquirer = {
type: 'input',
prefix: '',
name: 'input',
message: '',
choices: [],
}
}

public inquireOptions(promptOptions: string[]) {
this.optionsInquirer.message = Title.OptionsTitle
this.optionsInquirer.choices = promptOptions
return this.optionsInquirer
}

public inquireInput(title: string) {
this.inputInquirer.message = title
return this.inputInquirer
}

public inquireConfirmation(title: string) {
this.optionsInquirer.message = title
this.optionsInquirer.choices = [ConfirmOptions.Yes, ConfirmOptions.No]
return this.optionsInquirer
}

public async inquireMessage() {
this.inputInquirer.message = Title.MessageTitle
const message = await prompt([this.inputInquirer])

return message.input[0] === 'q' ? null : message.input
}
}
104 changes: 104 additions & 0 deletions demo-openid/src/Holder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import type {
OpenId4VciResolvedCredentialOffer,
OpenId4VcSiopResolvedAuthorizationRequest,
} from '@aries-framework/openid4vc'

import { AskarModule } from '@aries-framework/askar'
import {
W3cJwtVerifiableCredential,
W3cJsonLdVerifiableCredential,
DifPresentationExchangeService,
} from '@aries-framework/core'
import { OpenId4VcHolderModule } from '@aries-framework/openid4vc'
import { ariesAskar } from '@hyperledger/aries-askar-nodejs'

import { BaseAgent } from './BaseAgent'
import { Output } from './OutputClass'

function getOpenIdHolderModules() {
return {
askar: new AskarModule({ ariesAskar }),
openId4VcHolder: new OpenId4VcHolderModule(),
} as const
}

export class Holder extends BaseAgent<ReturnType<typeof getOpenIdHolderModules>> {
public constructor(port: number, name: string) {
super({ port, name, modules: getOpenIdHolderModules() })
}

public static async build(): Promise<Holder> {
const holder = new Holder(3000, 'OpenId4VcHolder ' + Math.random().toString())
await holder.initializeAgent('96213c3d7fc8d4d6754c7a0fd969598e')

return holder
}

public async resolveCredentialOffer(credentialOffer: string) {
return await this.agent.modules.openId4VcHolder.resolveCredentialOffer(credentialOffer)
}

public async requestAndStoreCredentials(
resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer,
credentialsToRequest: string[]
) {
const credentials = await this.agent.modules.openId4VcHolder.acceptCredentialOfferUsingPreAuthorizedCode(
resolvedCredentialOffer,
{
credentialsToRequest,
// TODO: add jwk support for holder binding
credentialBindingResolver: async () => ({
method: 'did',
didUrl: this.verificationMethod.id,
}),
}
)

const storedCredentials = await Promise.all(
credentials.map((credential) => {
if (credential instanceof W3cJwtVerifiableCredential || credential instanceof W3cJsonLdVerifiableCredential) {
return this.agent.w3cCredentials.storeCredential({ credential })
} else {
return this.agent.sdJwtVc.store(credential.compact)
}
})
)

return storedCredentials
}

public async resolveProofRequest(proofRequest: string) {
const resolvedProofRequest = await this.agent.modules.openId4VcHolder.resolveSiopAuthorizationRequest(proofRequest)

return resolvedProofRequest
}

public async acceptPresentationRequest(resolvedPresentationRequest: OpenId4VcSiopResolvedAuthorizationRequest) {
const presentationExchangeService = this.agent.dependencyManager.resolve(DifPresentationExchangeService)

if (!resolvedPresentationRequest.presentationExchange) {
throw new Error('Missing presentation exchange on resolved authorization request')
}

const submissionResult = await this.agent.modules.openId4VcHolder.acceptSiopAuthorizationRequest({
authorizationRequest: resolvedPresentationRequest.authorizationRequest,
presentationExchange: {
credentials: presentationExchangeService.selectCredentialsForRequest(
resolvedPresentationRequest.presentationExchange.credentialsForRequest
),
},
})

return submissionResult.serverResponse
}

public async exit() {
console.log(Output.Exit)
await this.agent.shutdown()
process.exit(0)
}

public async restart() {
await this.agent.shutdown()
}
}
Loading
Loading