-
Notifications
You must be signed in to change notification settings - Fork 207
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: crete openid4vc-holder package
Signed-off-by: Martin Auer <martin.auer97@gmail.com>
- Loading branch information
1 parent
282258e
commit 14c61ff
Showing
20 changed files
with
2,542 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
<p align="center"> | ||
<br /> | ||
<img | ||
alt="Hyperledger Aries logo" | ||
src="https://raw.githubusercontent.com/hyperledger/aries-framework-javascript/aa31131825e3331dc93694bc58414d955dcb1129/images/aries-logo.png" | ||
height="250px" | ||
/> | ||
</p> | ||
<h1 align="center"><b>Aries Framework JavaScript Open ID Connect For Verifiable Credentials Client Module</b></h1> | ||
<p align="center"> | ||
<a | ||
href="https://raw.githubusercontent.com/hyperledger/aries-framework-javascript/main/LICENSE" | ||
><img | ||
alt="License" | ||
src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" | ||
/></a> | ||
<a href="https://www.typescriptlang.org/" | ||
><img | ||
alt="typescript" | ||
src="https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg" | ||
/></a> | ||
<a href="https://www.npmjs.com/package/@aries-framework/openid4vc-holder" | ||
><img | ||
alt="@aries-framework/openid4vc-holder version" | ||
src="https://img.shields.io/npm/v/@aries-framework/openid4vc-holder" | ||
/></a> | ||
|
||
</p> | ||
<br /> | ||
|
||
Open ID Connect For Verifiable Credentials Holder Module for [Aries Framework JavaScript](https://github.com/hyperledger/aries-framework-javascript). | ||
|
||
### Installation | ||
|
||
Make sure you have set up the correct version of Aries Framework JavaScript according to the AFJ repository. | ||
|
||
```sh | ||
yarn add @aries-framework/openid4vc-holder | ||
``` | ||
|
||
### Quick start | ||
|
||
#### Requirements | ||
|
||
Before a credential can be requested, you need the issuer URI. This URI starts with `openid-initiate-issuance://` and is provided by the issuer. The issuer URI is commonly acquired by scanning a QR code. | ||
|
||
#### Module registration | ||
|
||
In order to get this module to work, we need to inject it into the agent. This makes the module's functionality accessible through the agent's `modules` api. | ||
|
||
```ts | ||
import { OpenId4VcHolderModule } from '@aries-framework/openid4vc-holder' | ||
|
||
const agent = new Agent({ | ||
config: { | ||
/* config */ | ||
}, | ||
dependencies: agentDependencies, | ||
modules: { | ||
openId4VcHolder: new OpenId4VcHolderModule(), | ||
/* other custom modules */ | ||
}, | ||
}) | ||
|
||
await agent.initialize() | ||
``` | ||
|
||
How the module is injected and the agent has been initialized, you can access the module's functionality through `agent.modules.openId4VcHolder`. | ||
|
||
#### Preparing a DID | ||
|
||
In order to request a credential, you'll need to provide a DID that the issuer will use for setting the credential subject. In the following snippet we create one for the sake of the example, but this can be any DID that has a _authentication verification method_ with key type `Ed25519`. | ||
|
||
```ts | ||
// first we create the DID | ||
const did = await agent.dids.create<KeyDidCreateOptions>({ | ||
method: 'key', | ||
options: { | ||
keyType: KeyType.Ed25519, | ||
}, | ||
}) | ||
|
||
// next we do some assertions and extract the key identifier (kid) | ||
|
||
if ( | ||
!did.didState.didDocument || | ||
!did.didState.didDocument.authentication || | ||
did.didState.didDocument.authentication.length === 0 | ||
) { | ||
throw new Error("Error creating did document, or did document has no 'authentication' verificationMethods") | ||
} | ||
|
||
const [verificationMethod] = did.didState.didDocument.authentication | ||
const kid = typeof verificationMethod === 'string' ? verificationMethod : verificationMethod.id | ||
``` | ||
|
||
#### Requesting the credential (Pre-Authorized) | ||
|
||
Now a credential issuance can be requested as follows. | ||
|
||
```ts | ||
const w3cCredentialRecord = await agent.modules.openId4VcHolder.requestCredentialPreAuthorized({ | ||
issuerUri, | ||
kid, | ||
checkRevocationState: false, | ||
}) | ||
|
||
console.log(w3cCredentialRecord) | ||
``` | ||
|
||
#### Full example | ||
|
||
```ts | ||
import { OpenId4VcHolderModule } from '@aries-framework/openid4vc-holder' | ||
import { agentDependencies } from '@aries-framework/node' // use @aries-framework/react-native for React Native | ||
import { Agent, KeyDidCreateOptions } from '@aries-framework/core' | ||
|
||
const run = async () => { | ||
const issuerUri = '' // The obtained issuer URI | ||
|
||
// Create the Agent | ||
const agent = new Agent({ | ||
config: { | ||
/* config */ | ||
}, | ||
dependencies: agentDependencies, | ||
modules: { | ||
openId4VcHolder: new OpenId4VcHolderModule(), | ||
/* other custom modules */ | ||
}, | ||
}) | ||
|
||
// Initialize the Agent | ||
await agent.initialize() | ||
|
||
// Create a DID | ||
const did = await agent.dids.create<KeyDidCreateOptions>({ | ||
method: 'key', | ||
options: { | ||
keyType: KeyType.Ed25519, | ||
}, | ||
}) | ||
|
||
// Assert DIDDocument is valid | ||
if ( | ||
!did.didState.didDocument || | ||
!did.didState.didDocument.authentication || | ||
did.didState.didDocument.authentication.length === 0 | ||
) { | ||
throw new Error("Error creating did document, or did document has no 'authentication' verificationMethods") | ||
} | ||
|
||
// Extract key identified (kid) for authentication verification method | ||
const [verificationMethod] = did.didState.didDocument.authentication | ||
const kid = typeof verificationMethod === 'string' ? verificationMethod : verificationMethod.id | ||
|
||
// Request the credential | ||
const w3cCredentialRecord = await agent.modules.openId4VcHolder.requestCredentialPreAuthorized({ | ||
issuerUri, | ||
kid, | ||
checkRevocationState: false, | ||
}) | ||
|
||
// Log the received credential | ||
console.log(w3cCredentialRecord) | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import type { Config } from '@jest/types' | ||
|
||
import base from '../../jest.config.base' | ||
|
||
import packageJson from './package.json' | ||
|
||
const config: Config.InitialOptions = { | ||
...base, | ||
|
||
displayName: packageJson.name, | ||
setupFilesAfterEnv: ['./tests/setup.ts'], | ||
} | ||
|
||
export default config |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
{ | ||
"name": "@aries-framework/openid4vc-holder", | ||
"main": "build/index", | ||
"types": "build/index", | ||
"version": "0.4.2", | ||
"files": [ | ||
"build" | ||
], | ||
"license": "Apache-2.0", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"homepage": "https://github.com/hyperledger/aries-framework-javascript/tree/main/packages/openid4vc-holder", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/hyperledger/aries-framework-javascript", | ||
"directory": "packages/openid4vc-holder" | ||
}, | ||
"scripts": { | ||
"build": "yarn run clean && yarn run compile", | ||
"clean": "rimraf ./build", | ||
"compile": "tsc -p tsconfig.build.json", | ||
"prepublishOnly": "yarn run build", | ||
"test": "jest" | ||
}, | ||
"dependencies": { | ||
"@aries-framework/core": "0.4.2", | ||
"@sphereon/oid4vci-client": "^0.7.3", | ||
"@sphereon/oid4vci-common": "^0.7.3", | ||
"@sphereon/ssi-types": "^0.17.5", | ||
"@stablelib/random": "^1.0.2", | ||
"fast-text-encoding": "^1.0.6" | ||
}, | ||
"devDependencies": { | ||
"@aries-framework/askar": "0.4.2", | ||
"@aries-framework/node": "0.4.2", | ||
"@hyperledger/aries-askar-nodejs": "^0.1.0", | ||
"@types/jsonpath": "^0.2.0", | ||
"nock": "^13.3.0", | ||
"rimraf": "^4.4.0", | ||
"typescript": "~4.9.5" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import type { | ||
GenerateAuthorizationUrlOptions, | ||
PreAuthCodeFlowOptions, | ||
AuthCodeFlowOptions, | ||
} from './OpenId4VcHolderServiceOptions' | ||
import type { W3cCredentialRecord } from '@aries-framework/core' | ||
|
||
import { injectable, AgentContext } from '@aries-framework/core' | ||
|
||
import { OpenId4VcHolderService } from './OpenId4VcHolderService' | ||
import { AuthFlowType } from './OpenId4VcHolderServiceOptions' | ||
|
||
/** | ||
* @public | ||
*/ | ||
@injectable() | ||
export class OpenId4VcHolderApi { | ||
private agentContext: AgentContext | ||
private openId4VcHolderService: OpenId4VcHolderService | ||
|
||
public constructor(agentContext: AgentContext, openId4VcHolderService: OpenId4VcHolderService) { | ||
this.agentContext = agentContext | ||
this.openId4VcHolderService = openId4VcHolderService | ||
} | ||
|
||
public async requestCredentialUsingPreAuthorizedCode( | ||
options: PreAuthCodeFlowOptions | ||
): Promise<W3cCredentialRecord[]> { | ||
// set defaults | ||
const verifyRevocationState = options.verifyCredentialStatus ?? true | ||
|
||
return this.openId4VcHolderService.requestCredential(this.agentContext, { | ||
...options, | ||
verifyCredentialStatus: verifyRevocationState, | ||
flowType: AuthFlowType.PreAuthorizedCodeFlow, | ||
}) | ||
} | ||
|
||
public async requestCredentialUsingAuthorizationCode(options: AuthCodeFlowOptions): Promise<W3cCredentialRecord[]> { | ||
// set defaults | ||
const checkRevocationState = options.verifyCredentialStatus ?? true | ||
|
||
return this.openId4VcHolderService.requestCredential(this.agentContext, { | ||
...options, | ||
verifyCredentialStatus: checkRevocationState, | ||
flowType: AuthFlowType.AuthorizationCodeFlow, | ||
}) | ||
} | ||
|
||
public async generateAuthorizationUrl(options: GenerateAuthorizationUrlOptions) { | ||
return this.openId4VcHolderService.generateAuthorizationUrl(options) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import type { DependencyManager, Module } from '@aries-framework/core' | ||
|
||
import { AgentConfig } from '@aries-framework/core' | ||
|
||
import { OpenId4VcHolderApi } from './OpenId4VcHolderApi' | ||
import { OpenId4VcHolderService } from './OpenId4VcHolderService' | ||
|
||
/** | ||
* @public | ||
*/ | ||
export class OpenId4VcHolderModule implements Module { | ||
public readonly api = OpenId4VcHolderApi | ||
|
||
/** | ||
* Registers the dependencies of the question answer module on the dependency manager. | ||
*/ | ||
public register(dependencyManager: DependencyManager) { | ||
// Warn about experimental module | ||
dependencyManager | ||
.resolve(AgentConfig) | ||
.logger.warn( | ||
"The '@aries-framework/openid4vc-holder' module is experimental and could have unexpected breaking changes. When using this module, make sure to use strict versions for all @aries-framework packages." | ||
) | ||
|
||
// Api | ||
dependencyManager.registerContextScoped(OpenId4VcHolderApi) | ||
|
||
// Services | ||
dependencyManager.registerSingleton(OpenId4VcHolderService) | ||
} | ||
} |
Oops, something went wrong.