@bedrock/vc-verifier 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +12 -0
- package/.github/workflows/main.yml +77 -0
- package/CHANGELOG.md +123 -0
- package/LICENSE.md +115 -0
- package/README.md +126 -0
- package/lib/challenges.js +199 -0
- package/lib/config.js +41 -0
- package/lib/documentLoader.js +83 -0
- package/lib/http.js +284 -0
- package/lib/index.js +55 -0
- package/lib/status.js +52 -0
- package/package.json +62 -0
- package/schemas/bedrock-vc-verifier.js +59 -0
- package/test/mocha/.eslintrc.cjs +9 -0
- package/test/mocha/10-provision.js +868 -0
- package/test/mocha/20-verify.js +392 -0
- package/test/mocha/30-credential-status.js +488 -0
- package/test/mocha/cert.pem +18 -0
- package/test/mocha/helpers.js +230 -0
- package/test/mocha/key.pem +28 -0
- package/test/mocha/mock-credential.json +39 -0
- package/test/mocha/mock.data.js +21 -0
- package/test/package.json +72 -0
- package/test/test.config.js +40 -0
- package/test/test.js +40 -0
package/.eslintrc.cjs
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
name: Bedrock Node.js CI
|
|
2
|
+
|
|
3
|
+
on: [push]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
lint:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
timeout-minutes: 10
|
|
9
|
+
strategy:
|
|
10
|
+
matrix:
|
|
11
|
+
node-version: [14.x]
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v2
|
|
14
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
15
|
+
uses: actions/setup-node@v1
|
|
16
|
+
with:
|
|
17
|
+
node-version: ${{ matrix.node-version }}
|
|
18
|
+
- run: npm install
|
|
19
|
+
- name: Run eslint
|
|
20
|
+
run: npm run lint
|
|
21
|
+
test-node:
|
|
22
|
+
needs: [lint]
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
timeout-minutes: 10
|
|
25
|
+
services:
|
|
26
|
+
mongodb:
|
|
27
|
+
image: mongo:4.2
|
|
28
|
+
ports:
|
|
29
|
+
- 27017:27017
|
|
30
|
+
strategy:
|
|
31
|
+
matrix:
|
|
32
|
+
node-version: [14.x]
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v2
|
|
35
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
36
|
+
uses: actions/setup-node@v1
|
|
37
|
+
with:
|
|
38
|
+
node-version: ${{ matrix.node-version }}
|
|
39
|
+
- run: |
|
|
40
|
+
npm install
|
|
41
|
+
cd test
|
|
42
|
+
npm install
|
|
43
|
+
- name: Run test with Node.js ${{ matrix.node-version }}
|
|
44
|
+
run: |
|
|
45
|
+
cd test
|
|
46
|
+
npm test
|
|
47
|
+
coverage:
|
|
48
|
+
needs: [test-node]
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
timeout-minutes: 10
|
|
51
|
+
services:
|
|
52
|
+
mongodb:
|
|
53
|
+
image: mongo:4.2
|
|
54
|
+
ports:
|
|
55
|
+
- 27017:27017
|
|
56
|
+
strategy:
|
|
57
|
+
matrix:
|
|
58
|
+
node-version: [14.x]
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@v2
|
|
61
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
62
|
+
uses: actions/setup-node@v1
|
|
63
|
+
with:
|
|
64
|
+
node-version: ${{ matrix.node-version }}
|
|
65
|
+
- run: |
|
|
66
|
+
npm install
|
|
67
|
+
cd test
|
|
68
|
+
npm install
|
|
69
|
+
- name: Generate coverage report
|
|
70
|
+
run: |
|
|
71
|
+
cd test
|
|
72
|
+
npm run coverage-ci
|
|
73
|
+
- name: Upload coverage to Codecov
|
|
74
|
+
uses: codecov/codecov-action@v2
|
|
75
|
+
with:
|
|
76
|
+
file: ./test/coverage/lcov.info
|
|
77
|
+
fail_ci_if_error: true
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# bedrock-vc-verifier ChangeLog
|
|
2
|
+
|
|
3
|
+
## 6.0.0 - 2022-04-06
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- **BREAKING**: Rename package to `@bedrock/vc-verifier`.
|
|
7
|
+
- **BREAKING**: Convert to module (ESM).
|
|
8
|
+
- **BREAKING**: Remove default export.
|
|
9
|
+
- **BREAKING**: Require node 14.x.
|
|
10
|
+
|
|
11
|
+
## 5.2.0 - 2022-03-14
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- Add missing dependencies `@digitalbazaar/webkms-client@10.0` and
|
|
15
|
+
`@digitalbazaar/edv-client@13.0` in test.
|
|
16
|
+
- Add coverage action in github workflows.
|
|
17
|
+
|
|
18
|
+
### Removed
|
|
19
|
+
- Remove unused dependency `crypto-ld@6.0`.
|
|
20
|
+
- Remove unused dependencies `veres-one-context`, `did-veres-one`, `crypto-ld`,
|
|
21
|
+
`did-context` and `bedrock-views` from test.
|
|
22
|
+
|
|
23
|
+
## 5.1.0 - 2022-03-12
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- Update dependencies:
|
|
27
|
+
- `@digitalbazaar/vc-status-list@2.1`.
|
|
28
|
+
|
|
29
|
+
## 5.0.0 - 2022-03-11
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- **BREAKING**: Update peer dependencies:
|
|
33
|
+
- `bedrock-service-core@3`
|
|
34
|
+
- `bedrock-service-context-store@3`
|
|
35
|
+
- `bedrock-did-io@6.1`.
|
|
36
|
+
|
|
37
|
+
## 4.0.0 - 2022-03-01
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
- **BREAKING**: Move zcap revocations to `/zcaps/revocations` to better
|
|
41
|
+
future proof.
|
|
42
|
+
- **BREAKING**: Require `bedrock-service-core@2`, `bedrock-service-agent@2`,
|
|
43
|
+
and `bedrock-service-context-store@2` peer dependencies.
|
|
44
|
+
|
|
45
|
+
## 3.1.0 - 2022-02-23
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
- Add default (dev mode) `app-identity` entry for `vc-verifier` service.
|
|
49
|
+
|
|
50
|
+
## 3.0.1 - 2022-02-21
|
|
51
|
+
|
|
52
|
+
### Changed
|
|
53
|
+
- Use `@digitalbazaar/vc-status-list-context` and updated bedrock-vc-status-list-context.
|
|
54
|
+
These dependencies have no changes other than moved package locations.
|
|
55
|
+
|
|
56
|
+
## 3.0.0 - 2022-02-20
|
|
57
|
+
|
|
58
|
+
### Changed
|
|
59
|
+
- **BREAKING**: Complete refactor to run on top of `bedrock-service*` modules. While
|
|
60
|
+
this version has similar functionality, its APIs and implementation are a clean
|
|
61
|
+
break from previous versions.
|
|
62
|
+
|
|
63
|
+
## 2.3.0 - 2022-02-15
|
|
64
|
+
|
|
65
|
+
### Changed
|
|
66
|
+
- Refactor documentLoader.
|
|
67
|
+
|
|
68
|
+
## 2.2.0 - 2022-02-09
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
- Add support for "StatusList2021Credential" status checks using
|
|
72
|
+
`vc-status-list@1.0`
|
|
73
|
+
- Add tests.
|
|
74
|
+
|
|
75
|
+
## 2.1.0 - 2021-09-14
|
|
76
|
+
|
|
77
|
+
### Added
|
|
78
|
+
- Add support for unsigned VPs.
|
|
79
|
+
|
|
80
|
+
## 2.0.2 - 2021-08-23
|
|
81
|
+
|
|
82
|
+
### Changed
|
|
83
|
+
- Update deps to fix multicodec bugs and set `verificationSuite` for `v1` to
|
|
84
|
+
`Ed25519VerificationKey2020` in config.
|
|
85
|
+
|
|
86
|
+
## 2.0.1 - 2021-05-28
|
|
87
|
+
|
|
88
|
+
### Fixed
|
|
89
|
+
- Fix bedrock peer dependencies.
|
|
90
|
+
|
|
91
|
+
## 2.0.0 - 2021-05-28
|
|
92
|
+
|
|
93
|
+
### Changed
|
|
94
|
+
- **BREAKING**: Remove `axios` and use `@digitalbazaar/http-client@1.1.0`.
|
|
95
|
+
Errors surfaced from `http-client` do not have the same signature as `axios`.
|
|
96
|
+
- **BREAKING**: Remove `cfg.ledgerHostname` and `cfg.mode` from `config.js`.
|
|
97
|
+
- **BREAKING**: Use [vc-revocation-list@3](https://github.com/digitalbazaar/vc-revocation-list/blob/main/CHANGELOG.md).
|
|
98
|
+
Revocation list credentials must have the same issuer value as the credential
|
|
99
|
+
to be revoked.
|
|
100
|
+
- **BREAKING**: Use [bedrock-did-io@3.0](https://github.com/digitalbazaar/bedrock-did-io/blob/main/CHANGELOG.md).
|
|
101
|
+
- Replace `vc-js` with `@digitalbazaar/vc`.
|
|
102
|
+
- Update to support ed25519 2020 signature suite.
|
|
103
|
+
- Update peerDeps and testDeps.
|
|
104
|
+
|
|
105
|
+
## 1.2.0 - 2021-03-03
|
|
106
|
+
|
|
107
|
+
### Fixed
|
|
108
|
+
|
|
109
|
+
- Only verify based on `options.checks`.
|
|
110
|
+
|
|
111
|
+
## 1.1.0 - 2020-05-18
|
|
112
|
+
|
|
113
|
+
### Added
|
|
114
|
+
|
|
115
|
+
- Implement W3C CCG VC Verification HTTP API.
|
|
116
|
+
|
|
117
|
+
## 1.0.0 - 2020-02-27
|
|
118
|
+
|
|
119
|
+
### Added
|
|
120
|
+
- API endpoint /vc/verify which can verify a presentation.
|
|
121
|
+
- Mock API endpoint /verifiers/:verifierId/verifications/:referenceId
|
|
122
|
+
- Positive tests for both endpoints.
|
|
123
|
+
- Utils to serialize errors in verification reports.
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Bedrock Non-Commercial License v1.0
|
|
2
|
+
===================================
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2011-2022 Digital Bazaar, Inc.
|
|
5
|
+
All rights reserved.
|
|
6
|
+
|
|
7
|
+
Summary
|
|
8
|
+
=======
|
|
9
|
+
|
|
10
|
+
This license allows the licensee to use Bedrock and its software modules
|
|
11
|
+
for non-commercial purposes such as self-study, research, personal
|
|
12
|
+
projects, or for evaluation purposes. If the licensee uses Bedrock
|
|
13
|
+
directly or indirectly to generate revenue, or to provide products or
|
|
14
|
+
services to more than 500 people (users), the licensee must immediately
|
|
15
|
+
obtain a non-profit or commercial license.
|
|
16
|
+
|
|
17
|
+
Examples
|
|
18
|
+
========
|
|
19
|
+
|
|
20
|
+
These are examples of cases that are allowed by this license:
|
|
21
|
+
|
|
22
|
+
* The licensee is an individual that creates Bedrock-dependent software for
|
|
23
|
+
personal use only.
|
|
24
|
+
* The licensee is an individual or group of students/researchers that uses
|
|
25
|
+
Bedrock to experiment with an idea for a non-commercial project.
|
|
26
|
+
* The licensee is a startup company that prototypes a Bedrock-dependent
|
|
27
|
+
product before they have cash flow and will be testing the prototype
|
|
28
|
+
software with less than 500 users. The service will not generate revenue
|
|
29
|
+
of any kind.
|
|
30
|
+
* The licensee is a for-profit organization that creates a product or
|
|
31
|
+
service that is used by less than 500 users and is built with or
|
|
32
|
+
integrates with Bedrock. The service must be exclusively provided for free
|
|
33
|
+
and no parent, subsidiary, agent, or affiliate organization may profit
|
|
34
|
+
from its direct or indirect use.
|
|
35
|
+
|
|
36
|
+
These cases require a non-profit or commercial license:
|
|
37
|
+
|
|
38
|
+
* The licensee is a non-profit that receives funding to create and/or run a
|
|
39
|
+
Bedrock-dependent service.
|
|
40
|
+
* The licensee is a startup company with Bedrock-dependent software that is
|
|
41
|
+
funded by another organization.
|
|
42
|
+
* The licensee is a startup company that is going into production with
|
|
43
|
+
Bedrock-dependent software.
|
|
44
|
+
* The licensee has more than 500 users using a Bedrock-dependent service
|
|
45
|
+
either directly or indirectly.
|
|
46
|
+
* The licensee is a medium to large organization that builds or integrates a
|
|
47
|
+
commercial product or service with Bedrock.
|
|
48
|
+
|
|
49
|
+
THE LICENSE
|
|
50
|
+
===========
|
|
51
|
+
|
|
52
|
+
This section and all subsequent sections of this document constitute the
|
|
53
|
+
agreement between the licensee and Digital Bazaar, Inc.
|
|
54
|
+
|
|
55
|
+
DEFINITIONS
|
|
56
|
+
===========
|
|
57
|
+
|
|
58
|
+
* Product - The Bedrock software and any modules associated with Bedrock
|
|
59
|
+
where Digital Bazaar, Inc. owns the copyright.
|
|
60
|
+
|
|
61
|
+
CONDITIONS
|
|
62
|
+
==========
|
|
63
|
+
|
|
64
|
+
Redistribution and use in source and binary forms, with or without
|
|
65
|
+
modification, are permitted for NON-COMMERCIAL PURPOSES as long as the
|
|
66
|
+
following conditions are met:
|
|
67
|
+
|
|
68
|
+
1. Any use of the Product must not generate revenue for the licensee or
|
|
69
|
+
any parent, subsidiary, agent, or affiliate of the licensee. Use of
|
|
70
|
+
Product includes, but is not limited to, interacting with any of the
|
|
71
|
+
licensee's Product-dependent products or services over a network.
|
|
72
|
+
|
|
73
|
+
2. The aggregate number of individual people (users) of the licensee's
|
|
74
|
+
products or services that use Product must be less than 500.
|
|
75
|
+
|
|
76
|
+
3. Redistributions of source code must retain the above copyright notice
|
|
77
|
+
intact, this list of conditions and the following disclaimer.
|
|
78
|
+
|
|
79
|
+
4. Redistributions in binary form must reproduce the above copyright
|
|
80
|
+
notice, this license and the following disclaimer in the documentation and
|
|
81
|
+
on a web page available via interactive use and/or other materials
|
|
82
|
+
provided with the distribution.
|
|
83
|
+
|
|
84
|
+
5. Neither the name of the copyright holder, the names of its
|
|
85
|
+
contributors, nor any trademarks held by the copyright holder may be used
|
|
86
|
+
to endorse or promote products or services built using the Product without
|
|
87
|
+
specific prior written permission.
|
|
88
|
+
|
|
89
|
+
6. Any modifications are clearly outlined in release documentation and are
|
|
90
|
+
specifically mentioned as not being a part of an official Product release.
|
|
91
|
+
No additional restrictions to this license may be made when distributing
|
|
92
|
+
modifications.
|
|
93
|
+
|
|
94
|
+
7. For the avoidance of doubt, this license prohibits sublicensing of the
|
|
95
|
+
Product.
|
|
96
|
+
|
|
97
|
+
8. Any breach of this license by licensee must be resolved within 30 days.
|
|
98
|
+
Failure to do so results in the termination of this license.
|
|
99
|
+
|
|
100
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
|
101
|
+
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
102
|
+
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
103
|
+
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
104
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
105
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
106
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
107
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
108
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
109
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
110
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
111
|
+
|
|
112
|
+
To obtain a non-profit or commercial license for Product, please contact
|
|
113
|
+
Digital Bazaar, Inc. at the following email address:
|
|
114
|
+
|
|
115
|
+
Digital Bazaar <support@digitalbazaar.com>
|
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Bedrock VC Verifier API module _(bedrock-vc-verifier)_
|
|
2
|
+
|
|
3
|
+
[](https://github.com/digitalbazaar/bedrock-vc-verifier/actions?query=workflow%3A%22Bedrock+Node.js+CI%22)
|
|
4
|
+
[](https://npm.im/bedrock-vc-verifier)
|
|
5
|
+
|
|
6
|
+
> A VC Verifier API library for use with Bedrock applications.
|
|
7
|
+
|
|
8
|
+
## Table of Contents
|
|
9
|
+
|
|
10
|
+
- [Background](#background)
|
|
11
|
+
- [Security](#security)
|
|
12
|
+
- [Install](#install)
|
|
13
|
+
- [Usage](#usage)
|
|
14
|
+
- [Contribute](#contribute)
|
|
15
|
+
- [Commercial Support](#commercial-support)
|
|
16
|
+
- [License](#license)
|
|
17
|
+
|
|
18
|
+
## Background
|
|
19
|
+
|
|
20
|
+
* [Verifiable Credentials HTTP API v0.3](https://w3c-ccg.github.io/vc-http-api/) specification.
|
|
21
|
+
|
|
22
|
+
## Security
|
|
23
|
+
|
|
24
|
+
TBD
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
- Node.js 14+ is required.
|
|
29
|
+
|
|
30
|
+
### NPM
|
|
31
|
+
|
|
32
|
+
To install via NPM:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
npm install --save @bedrock/vc-verifier
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Development
|
|
39
|
+
|
|
40
|
+
To install locally (for development):
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
git clone https://github.com/digitalbazaar/bedrock-vc-verifier.git
|
|
44
|
+
cd bedrock-vc-verifier
|
|
45
|
+
npm install
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
In `lib/index.js`:
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
import '@bedrock/vc-verifier';
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Verifier HTTP API
|
|
57
|
+
|
|
58
|
+
This module exposes the following API endpoints.
|
|
59
|
+
|
|
60
|
+
#### Verify Presentation - `POST /vc/verify`
|
|
61
|
+
|
|
62
|
+
Example request:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"presentation": {},
|
|
67
|
+
"challenge": "...",
|
|
68
|
+
"domain": "issuer.example.com"
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
#### Verify Credentials - `POST /verifier/credentials`
|
|
73
|
+
|
|
74
|
+
Alias: `/instances/:instanceId/credentials/verify`
|
|
75
|
+
|
|
76
|
+
Optionally performs status checks using the `vc-revocation-list` or
|
|
77
|
+
`vc-status-list` library.
|
|
78
|
+
|
|
79
|
+
Example request:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"verifiableCredential": {},
|
|
84
|
+
"options": {
|
|
85
|
+
"checks": ["proof", "credentialStatus"]
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### Verify Presentations - `POST /verifier/presentations`
|
|
91
|
+
|
|
92
|
+
Alias: `/instances/:instanceId/presentations/verify`
|
|
93
|
+
|
|
94
|
+
Optionally performs status checks using the `vc-revocation-list` or
|
|
95
|
+
`vc-status-list` library.
|
|
96
|
+
|
|
97
|
+
Example request:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"verifiablePresentation": {},
|
|
102
|
+
"options": {
|
|
103
|
+
"challenge": "...",
|
|
104
|
+
"checks": ["proof", "credentialStatus"],
|
|
105
|
+
"domain": "issuer.exmaple.com"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Contribute
|
|
111
|
+
|
|
112
|
+
See [the contribute file](https://github.com/digitalbazaar/bedrock/blob/master/CONTRIBUTING.md)!
|
|
113
|
+
|
|
114
|
+
PRs accepted.
|
|
115
|
+
|
|
116
|
+
If editing the Readme, please conform to the
|
|
117
|
+
[standard-readme](https://github.com/RichardLitt/standard-readme) specification.
|
|
118
|
+
|
|
119
|
+
## Commercial Support
|
|
120
|
+
|
|
121
|
+
Commercial support for this library is available upon request from
|
|
122
|
+
Digital Bazaar: support@digitalbazaar.com
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
[Bedrock Non-Commercial License v1.0](LICENSE.md) © Digital Bazaar
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
import * as bedrock from '@bedrock/core';
|
|
5
|
+
import * as database from '@bedrock/mongodb';
|
|
6
|
+
import assert from 'assert-plus';
|
|
7
|
+
import {createRequire} from 'module';
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const {generateId, decodeId} = require('bnid');
|
|
10
|
+
|
|
11
|
+
const {util: {BedrockError}} = bedrock;
|
|
12
|
+
|
|
13
|
+
const COLLECTION_NAME = 'vc-verifier-challenge';
|
|
14
|
+
|
|
15
|
+
bedrock.events.on('bedrock-mongodb.ready', async () => {
|
|
16
|
+
await database.openCollections([COLLECTION_NAME]);
|
|
17
|
+
|
|
18
|
+
await database.createIndexes([{
|
|
19
|
+
collection: COLLECTION_NAME,
|
|
20
|
+
fields: {'challenge.value': 1},
|
|
21
|
+
options: {unique: true, background: false}
|
|
22
|
+
}, {
|
|
23
|
+
// automatically expire challenges
|
|
24
|
+
collection: COLLECTION_NAME,
|
|
25
|
+
fields: {'challenge.expires': 1},
|
|
26
|
+
options: {
|
|
27
|
+
unique: false,
|
|
28
|
+
background: false,
|
|
29
|
+
expireAfterSeconds: 0
|
|
30
|
+
}
|
|
31
|
+
}]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Generates and stores a challenge to be used within the configured time
|
|
36
|
+
* frame.
|
|
37
|
+
*
|
|
38
|
+
* @param {object} options - The options to use.
|
|
39
|
+
* @param {object} options.verifierId - The verifier instance ID.
|
|
40
|
+
*
|
|
41
|
+
* @returns {Promise<string>} The challenge.
|
|
42
|
+
*/
|
|
43
|
+
export async function createChallenge({verifierId}) {
|
|
44
|
+
// generate challenge
|
|
45
|
+
const challenge = await _generateChallenge();
|
|
46
|
+
// insert and return challenge
|
|
47
|
+
const {ttl} = bedrock.config['vc-verifier'].challenges;
|
|
48
|
+
await _insert({challenge, verifierId, ttl});
|
|
49
|
+
return challenge;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Verifies that a challenge has not expired.
|
|
54
|
+
*
|
|
55
|
+
* @param {object} options - The options to use.
|
|
56
|
+
* @param {object} options.verifierId - The verifier instance ID.
|
|
57
|
+
* @param {string} options.challenge - The challenge to verify.
|
|
58
|
+
*
|
|
59
|
+
* @returns {Promise<object>} `{verified: <boolean>, uses, error?}`.
|
|
60
|
+
*/
|
|
61
|
+
export async function verifyChallenge({verifierId, challenge} = {}) {
|
|
62
|
+
try {
|
|
63
|
+
// try to use challenge
|
|
64
|
+
const record = await _use({challenge, verifierId});
|
|
65
|
+
return {verified: true, uses: record.challenge.uses};
|
|
66
|
+
} catch(error) {
|
|
67
|
+
return {verified: false, error};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function _generateChallenge() {
|
|
72
|
+
// 128-bit random number, base58 multibase + multihash encoded
|
|
73
|
+
return generateId({
|
|
74
|
+
bitLength: 128,
|
|
75
|
+
encoding: 'base58',
|
|
76
|
+
multibase: true,
|
|
77
|
+
multihash: true
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function _decodeChallenge({challenge}) {
|
|
82
|
+
// convert to `Buffer` for database storage savings
|
|
83
|
+
try {
|
|
84
|
+
return Buffer.from(decodeId({
|
|
85
|
+
id: challenge,
|
|
86
|
+
encoding: 'base58',
|
|
87
|
+
multibase: true,
|
|
88
|
+
multihash: true,
|
|
89
|
+
expectedSize: 16
|
|
90
|
+
}));
|
|
91
|
+
} catch(e) {
|
|
92
|
+
throw new BedrockError(
|
|
93
|
+
'Invalid challenge.', 'DataError', {
|
|
94
|
+
httpStatusCode: 400,
|
|
95
|
+
public: true
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Inserts a new challenge into storage.
|
|
102
|
+
*
|
|
103
|
+
* @param {object} options - The options to use.
|
|
104
|
+
* @param {string} options.challenge - The challenge to upsert.
|
|
105
|
+
* @param {number} options.ttl - The time to live for the challenge.
|
|
106
|
+
*
|
|
107
|
+
* @returns {Promise<object>} Resolves with an object representing the
|
|
108
|
+
* challenge record.
|
|
109
|
+
*/
|
|
110
|
+
async function _insert({challenge, ttl} = {}) {
|
|
111
|
+
assert.string(challenge, 'challenge');
|
|
112
|
+
assert.number(ttl, 'ttl');
|
|
113
|
+
challenge = _decodeChallenge({challenge});
|
|
114
|
+
|
|
115
|
+
// insert the configuration and get the updated record
|
|
116
|
+
const now = Date.now();
|
|
117
|
+
const meta = {created: now, updated: now};
|
|
118
|
+
const expires = new Date(now + ttl);
|
|
119
|
+
const record = {
|
|
120
|
+
challenge: {
|
|
121
|
+
value: challenge,
|
|
122
|
+
expires,
|
|
123
|
+
uses: 0
|
|
124
|
+
},
|
|
125
|
+
meta
|
|
126
|
+
};
|
|
127
|
+
try {
|
|
128
|
+
const collection = database.collections[COLLECTION_NAME];
|
|
129
|
+
const result = await collection.insertOne(record);
|
|
130
|
+
return result.ops[0];
|
|
131
|
+
} catch(e) {
|
|
132
|
+
if(!database.isDuplicateError(e)) {
|
|
133
|
+
throw e;
|
|
134
|
+
}
|
|
135
|
+
// should never happen; challenge values are sufficiently large and random
|
|
136
|
+
throw new BedrockError(
|
|
137
|
+
'Duplicate challenge.',
|
|
138
|
+
'DuplicateError', {
|
|
139
|
+
public: true,
|
|
140
|
+
httpStatusCode: 409
|
|
141
|
+
}, e);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Finds and updates a challenge's `uses`.
|
|
147
|
+
*
|
|
148
|
+
* @param {object} options - Options to use.
|
|
149
|
+
* @param {string} options.challenge - The challenge to mark as used.
|
|
150
|
+
* @param {boolean} [options.explain] - An optional explain boolean.
|
|
151
|
+
*
|
|
152
|
+
* @returns {Promise<object | ExplainObject>} Resolves with an object
|
|
153
|
+
* representing the challenge record or an ExplainObject if `explain=true`.
|
|
154
|
+
*/
|
|
155
|
+
async function _use({challenge, explain = false} = {}) {
|
|
156
|
+
assert.string(challenge, 'challenge');
|
|
157
|
+
assert.bool(explain, 'explain');
|
|
158
|
+
challenge = _decodeChallenge({challenge});
|
|
159
|
+
|
|
160
|
+
const collection = database.collections[COLLECTION_NAME];
|
|
161
|
+
const query = {'challenge.value': challenge};
|
|
162
|
+
const $inc = {
|
|
163
|
+
'challenge.uses': 1,
|
|
164
|
+
};
|
|
165
|
+
const $set = {
|
|
166
|
+
'meta.updated': Date.now()
|
|
167
|
+
};
|
|
168
|
+
const options = {
|
|
169
|
+
...database.writeOptions,
|
|
170
|
+
// return document after the update
|
|
171
|
+
returnDocument: 'after'
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
if(explain) {
|
|
175
|
+
// 'find().limit(1)' is used here because 'updateOne()' doesn't return a
|
|
176
|
+
// cursor which allows the use of the explain function.
|
|
177
|
+
const cursor = await collection.find(query).limit(1);
|
|
178
|
+
return cursor.explain('executionStats');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// this upsert cannot trigger duplicate error; no try/catch needed
|
|
182
|
+
const result = await collection.findOneAndUpdate(
|
|
183
|
+
query, {$inc, $set}, options);
|
|
184
|
+
|
|
185
|
+
if(!result.value) {
|
|
186
|
+
// no document found, challenge invalid or expired
|
|
187
|
+
throw new BedrockError(
|
|
188
|
+
'Invalid or expired challenge.', 'DataError', {
|
|
189
|
+
httpStatusCode: 400,
|
|
190
|
+
public: true
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return result.value;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @typedef ExplainObject - MongoDB explain object.
|
|
199
|
+
*/
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
import {config} from '@bedrock/core';
|
|
5
|
+
import '@bedrock/app-identity';
|
|
6
|
+
|
|
7
|
+
const cfg = config['vc-verifier'] = {};
|
|
8
|
+
|
|
9
|
+
cfg.challenges = {
|
|
10
|
+
// by default, challenges must be used within 15 minutes
|
|
11
|
+
ttl: 1000 * 60 * 15
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// document loader configuration for the verifier; all verifier instances
|
|
15
|
+
// will securely load DID documents using `bedrock-did-io` and any contexts
|
|
16
|
+
// that have been specifically added to them; these config options below
|
|
17
|
+
// also allow any verifier instance to optionally load `http` and `https`
|
|
18
|
+
// documents directly from the Web
|
|
19
|
+
cfg.documentLoader = {
|
|
20
|
+
// `true` enables all verifiers to fetch `http` documents from the Web
|
|
21
|
+
http: false,
|
|
22
|
+
// `true` enables all verifiers to fetch `https` documents from the Web
|
|
23
|
+
https: true
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
cfg.supportedSuites = ['Ed25519Signature2018', 'Ed25519Signature2020'];
|
|
27
|
+
|
|
28
|
+
cfg.routes = {
|
|
29
|
+
challenges: '/challenges',
|
|
30
|
+
credentialsVerify: '/credentials/verify',
|
|
31
|
+
presentationsVerify: '/presentations/verify'
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// create dev application identity for vc-verifier (must be overridden in
|
|
35
|
+
// deployments) ...and `ensureConfigOverride` has already been set via
|
|
36
|
+
// `bedrock-app-identity` so it doesn't have to be set here
|
|
37
|
+
config['app-identity'].seeds.services['vc-verifier'] = {
|
|
38
|
+
id: 'did:key:z6Mkff1TPyQ7nh3qXYGe3gJn26aaLX5ACJBi7s6Ei6MW3qAc',
|
|
39
|
+
seedMultibase: 'z1AYfdySL6F2wHarpfjSo1GaMaCW11TWbKyTP4eKBosmiDw',
|
|
40
|
+
serviceType: 'vc-verifier'
|
|
41
|
+
};
|