Skip to content

Commit

Permalink
additional cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
kezike committed Apr 24, 2024
1 parent 7b863ba commit aecec73
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 88 deletions.
31 changes: 25 additions & 6 deletions .status-service.env
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,30 @@
# ONLY for dev when need https; default is false
# ENABLE_HTTPS_FOR_DEV=false

# the CRED_STATUS_* values are used to instantiate the status list manager
# Replace with your own values as described in the README
CRED_STATUS_REPO_OWNER=jchartrand
CRED_STATUS_REPO_NAME=status-test-three
CRED_STATUS_META_REPO_NAME=status-test-meta-three
CRED_STATUS_ACCESS_TOKEN=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
# replace the following did seed with your own

# Git specific environment variables
CRED_STATUS_SERVICE=github
CRED_STATUS_DID_SEED=z1AackbUm8U69ohKnihoRRFkXcXJd4Ra1PkAboQ2ZRy1ngB
CRED_STATUS_REPO_OWNER=digitalcredentials
CRED_STATUS_REPO_NAME=credential-status-test-jc
CRED_STATUS_REPO_ID=12345678 # only required when CRED_STATUS_SERVICE = 'gitlab'
CRED_STATUS_META_REPO_NAME=credential-status-metadata-test-jc
CRED_STATUS_META_REPO_ID=87654321 # only required when CRED_STATUS_SERVICE = 'gitlab'
CRED_STATUS_ACCESS_TOKEN=REPLACE_THIS_WITH_A_GITHUB_ACCESS_TOKEN

# Database specific environment variables
CRED_STATUS_SERVICE=mongodb
CRED_STATUS_DID_SEED=z1AackbUm8U69ohKnihoRRFkXcXJd4Ra1PkAboQ2ZRy1ngB
STATUS_CRED_SITE_ORIGIN=https://credentials.example.edu
CRED_STATUS_DB_URL=mongodb+srv://user:pass@domain.mongodb.net?retryWrites=false
CRED_STATUS_DB_HOST=domain.mongodb.net # ignored if CRED_STATUS_DB_URL is configured
CRED_STATUS_DB_PORT=27017 # ignored if CRED_STATUS_DB_URL is configured
CRED_STATUS_DB_USER=testuser # ignored if CRED_STATUS_DB_URL is configured
CRED_STATUS_DB_PASS=testpass # ignored if CRED_STATUS_DB_URL is configured
CRED_STATUS_DB_NAME=
STATUS_CRED_TABLE_NAME=
USER_CRED_TABLE_NAME=
CONFIG_TABLE_NAME=
EVENT_TABLE_NAME=
CRED_EVENT_TABLE_NAME=
71 changes: 32 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Note that you needn't clone this repository to use the issuer - you can simply r

## Summary

Use this service to issue [Verifiable Credentials](https://www.w3.org/TR/vc-data-model/) with a [status](https://www.w3.org/TR/vc-bitstring-status-list/) that can later be updated to revoke or suspend the credential.
Use this service to issue [Verifiable Credentials](https://www.w3.org/TR/vc-data-model-2.0/) with a [status](https://www.w3.org/TR/vc-bitstring-status-list/) that can later be updated to revoke or suspend the credential.

Implements two [VC-API](https://w3c-ccg.github.io/vc-api/) HTTP endpoints:

Expand All @@ -61,7 +61,7 @@ Docker has made this straightforward, with [installers for Windows, Mac, and Lin

Create a file called `docker-compose.yml` and add the following:

```
```yaml
version: '3.5'
services:
coordinator:
Expand All @@ -76,13 +76,15 @@ services:
From the terminal in the same directory that contains your `docker-compose.yml` file, run:

```docker compose up```
```bash
docker compose up
```

### Issue

Issue cryptographically signed credentials by posting unsigned Verifiable Credentials to the issue endpoint, which signs the credential and returns it. Try out your test issuer with this cURL command, which you simply paste into the terminal:

```
```bash
curl --location 'http://localhost:4005/instance/test/credentials/issue' \
--header 'Content-Type: application/json' \
--data-raw '{
Expand Down Expand Up @@ -134,7 +136,7 @@ curl --location 'http://localhost:4005/instance/test/credentials/issue' \

This should return a fully formed and signed credential printed to the terminal, that should look something like this (it will be all smushed up, but you can format it in something like [JSONLint](https://jsonlint.com)):

```
```json
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
Expand Down Expand Up @@ -188,7 +190,6 @@ This should return a fully formed and signed credential printed to the terminal,
"proofValue": "z5fk6gq9upyZvcFvJdRdeL5KmvHr69jxEkyDEd2HyQdyhk9VnDEonNSmrfLAcLEDT9j4gGdCG24WHhojVHPbRsNER"
}
}
```

WARNING: DO NOT USE THIS TO ISSUE `REAL` CREDENTIALS UNTIL YOU'VE [SET YOUR OWN SIGNING KEY](#generate-a-new-key)
Expand Down Expand Up @@ -237,17 +238,17 @@ The `did:key` DID is one of the simpler DID implementations and doesn't require
We've tried to simplify key generation by providing convenience endpoints in the issuer that you can use to generate a brand new key. You can generate a DID key with these cURL commands (in a terminal):

- `did:key`:

```
```bash
curl --location 'http://localhost:4005/did-key-generator'
```
- `did:web`:

```
```bash
curl \
--location 'localhost:4006/did-web-generator' \
--header 'Content-Type: application/json' \
--data '{"url": "https://raw.githubusercontent.com/user-or-org/did-web-test/main"}'
--data-raw '{
"url": "https://raw.githubusercontent.com/user-or-org/did-web-test/main"
}'
```

These commands will return a JSON document that contains the following data:
Expand All @@ -258,7 +259,7 @@ These commands will return a JSON document that contains the following data:

Here is an example output for `did:key`:

```
```json
{
"seed": "z1AjQUBZCNoiyPUC8zbbF29gLdZtHRqT6yPdFGtqJa5VfQ6",
"did": "did:key:z6MkweTn1XVAiFfHjiH48oLknjNqRs43ayzguc8G8VbEAVm4",
Expand Down Expand Up @@ -287,7 +288,7 @@ Here is an example output for `did:key`:

...and here is an example output for `did:web` \*:

```
```json
{
"seed": "z1AcNXDnko1P6QMiZ3bxsraNvVtRbpXKeE8GNLDXjBJ5UHz",
"decodedSeed": {...},
Expand Down Expand Up @@ -386,7 +387,7 @@ where `econ101` is the lower casing of the tenant name you'd have set in the env
If you set a token for the tenant, you'll have to include that token in the auth header as a Bearer token. A cURL command to issue from the `econ101` tenant would then look exactly like the call in the example above, but with the bearer token set in the `Authorization` header like so:
```
```bash
curl --location 'http://localhost:4005/instance/econ101/credentials/issue' \
--header 'Authorization: Bearer 988DKLAJH93KDSFV' \
--header 'Content-Type: application/json' \
Expand Down Expand Up @@ -493,35 +494,25 @@ The DCC provides another issuing service called the [exchange-coordinator](https

### Revoking and Suspending

Revocation and suspension are more fully explained in the [Bitstring Status List](https://www.w3.org/TR/vc-bitstring-status-list/) specification and our implemenations thereof, but effectively, it amounts to POSTing an object to the revocation endpoint, like so:
Revocation and suspension are more fully explained in the [Bitstring Status List](https://www.w3.org/TR/vc-bitstring-status-list/) specification and our implemenations thereof, but effectively, it amounts to POSTing an object to the status update endpoint, like so:

```
{
credentialId: 'id_added_by_status_manager_to_credentialStatus_propery_of_VC',
credentialStatus: [{
type: 'BitstringStatusListCredential',
status: 'revoked'
```bash
curl --location 'http://localhost:4005/instance/test/credentials/status' \
--header 'Content-Type: application/json' \
--data-raw '{
"credentialId": "urn:uuid:951b475e-b795-43bc-ba8f-a2d01efd2eb1",
"credentialStatus": [{
"type": "BitstringStatusListCredential",
"status": "revoked"
}]
}
```

The important part there is the `credentialId`, which is listed in the `credentialStatus` section of the issued credential (`credentialStatus` is added by the status service), and which you have to store at the point when you issue the credential. The `credentialStatus` section looks like this:

```
"credentialStatus": {
"id": "https://digitalcredentials.github.io/credential-status-jc-test/XA5AAK1PV4#16",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": 16,
"statusListCredential": "https://digitalcredentials.github.io/credential-status-jc-test/XA5AAK1PV4"
}
}'
```

...and the ID you need is in the `id` property.
The important part there is the `credentialId`. If an issuer provides an `id` field on a credential, the status service will pick this up and save the credential under this ID, as long as it is a valid VC ID, per [these guidelines](https://www.w3.org/TR/vc-data-model-2.0/#identifiers) (e.g., URL, URN). If an ID is not provided, the status service will automatically generate one and attach it to the credential as the `id` field.

So again, an important point here is that you must store the `credentialStatus.id` value for all credentials that you issue. A common approach might be to add another column to whatever local database you are using for your credential records, which would then later make it easier for you to find the ID you need by searching the other fields like student name or student ID.
It is important that you save this value in your system during the issuance process, as you will need it to perform revocations and suspensions in the future. A common approach might be to add another column to whatever local database you are using for your credential records, which would then later make it easier for you to find the ID you need by searching the other fields like student name or student ID.

NOTE: You'll of course have to enable [status updates](#enable-revocation-and-suspension) for this to work. If you've only done the Quick Start then you'll not be able to revoke and suspend.
**Note:** You'll of course have to enable [status updates](#enable-revocation-and-suspension) for this to work. If you've only done the Quick Start then you'll not be able to revoke and suspend.

## Learner Credential Wallet

Expand All @@ -537,7 +528,7 @@ When running locally, the system picks up environment variables from the standar

Clone code, cd into the directory, and run:

```
```bash
npm install
npm run dev
```
Expand All @@ -546,7 +537,9 @@ npm run dev

Testing uses `supertest`, `mocha`, and `nock` to test the endpoints. To run tests:

```npm run test```
```bash
npm run test
```

Note that when testing we don't actually want to make live HTTP calls to the services,
so we've used nock to intercept the HTTP calls and return precanned data.
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@digigatlcredentials/issuer-coordinator",
"name": "@digitalcredentials/issuer-coordinator",
"version": "0.0.0",
"private": true,
"type": "module",
Expand Down
7 changes: 6 additions & 1 deletion src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,12 @@ export async function build (opts = {}) {
})

// updates the status
// the body will look like: {credentialId: '23kdr', credentialStatus: [{type: 'BitstringStatusListCredential', status: 'revoked'}]}
/*
{
"credentialId": "urn:uuid:951b475e-b795-43bc-ba8f-a2d01efd2eb1",
"credentialStatus": [{ "type": "BitstringStatusListCredential", "status": "revoked" }]
}
*/
app.post('/instance/:tenantName/credentials/status',
async (req, res, next) => {
if (!enableStatusService) return res.status(405).send('The status service has not been enabled.')
Expand Down
5 changes: 4 additions & 1 deletion src/app.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ describe('api', () => {
before(async () => {
testTenantToken = process.env.TENANT_TOKEN_PROTECTED_TEST
testTenantToken2 = process.env.TENANT_TOKEN_PROTECTED_TEST_2
statusUpdateBody = { credentialId: 'urn:uuid:951b475e-b795-43bc-ba8f-a2d01efd2eb1', credentialStatus: [{ type: 'BitstringStatusListCredential', status: 'revoked' }] }
statusUpdateBody = {
credentialId: 'urn:uuid:951b475e-b795-43bc-ba8f-a2d01efd2eb1',
credentialStatus: [{ type: 'BitstringStatusListCredential', status: 'revoked' }]
}
})

after(() => {
Expand Down
46 changes: 32 additions & 14 deletions src/test-fixtures/nocks/protected_status_signing.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,22 @@ const signedVcWithStatus = {
},
type: 'AchievementSubject'
},
credentialStatus: {
id: 'https://jchartrand.github.io/status-test-three/DKSPRCX9WB#1',
statusListCredential: 'https://jchartrand.github.io/status-test-three/DKSPRCX9WB',
statusListIndex: 1,
statusPurpose: 'revocation',
type: 'BitstringStatusListEntry'
},
credentialStatus: [
{
id: 'https://digitalcredentials.github.io/credential-status-jc-test/XA5AAK1PV4#2',
type: 'BitstringStatusListEntry',
statusPurpose: 'revocation',
statusListIndex: 2,
statusListCredential: 'https://digitalcredentials.github.io/credential-status-jc-test/XA5AAK1PV4'
},
{
id: 'https://digitalcredentials.github.io/credential-status-jc-test/DKSPRCX9WB#5',
type: 'BitstringStatusListEntry',
statusPurpose: 'suspension',
statusListIndex: 5,
statusListCredential: 'https://digitalcredentials.github.io/credential-status-jc-test/DKSPRCX9WB'
}
],
proof: {
created: '2023-08-23T12:44:15Z',
proofPurpose: 'assertionMethod',
Expand Down Expand Up @@ -139,13 +148,22 @@ const unsignedVcWithStatus = {
name: 'Introduction to Computer Science - CS50x'
}
},
credentialStatus: {
id: 'https://jchartrand.github.io/status-test-three/DKSPRCX9WB#1',
type: 'BitstringStatusListEntry',
statusPurpose: 'revocation',
statusListIndex: 1,
statusListCredential: 'https://jchartrand.github.io/status-test-three/DKSPRCX9WB'
}
credentialStatus: [
{
id: 'https://digitalcredentials.github.io/credential-status-jc-test/XA5AAK1PV4#2',
type: 'BitstringStatusListEntry',
statusPurpose: 'revocation',
statusListIndex: 2,
statusListCredential: 'https://digitalcredentials.github.io/credential-status-jc-test/XA5AAK1PV4'
},
{
id: 'https://digitalcredentials.github.io/credential-status-jc-test/DKSPRCX9WB#5',
type: 'BitstringStatusListEntry',
statusPurpose: 'suspension',
statusListIndex: 5,
statusListCredential: 'https://digitalcredentials.github.io/credential-status-jc-test/DKSPRCX9WB'
}
]
}

export default () => {
Expand Down
5 changes: 4 additions & 1 deletion src/test-fixtures/nocks/protected_status_update.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import nock from 'nock'

export default () => {
nock('http://localhost:4008', { encodedQueryParams: true })
.post('/credentials/status', { credentialId: 'urn:uuid:951b475e-b795-43bc-ba8f-a2d01efd2eb1', credentialStatus: [{ type: 'BitstringStatusListCredential', status: 'revoked' }] })
.post('/credentials/status', {
credentialId: 'urn:uuid:951b475e-b795-43bc-ba8f-a2d01efd2eb1',
credentialStatus: [{ type: 'BitstringStatusListCredential', status: 'revoked' }]
})
.reply(200, { code: 200, message: 'Credential status successfully updated.' }, [
'X-Powered-By',
'Express',
Expand Down
5 changes: 4 additions & 1 deletion src/test-fixtures/nocks/unknown_status_id_nock.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import nock from 'nock'

export default () => {
nock('http://localhost:4008', { encodedQueryParams: true })
.post('/credentials/status', { credentialId: 'kj09ij', credentialStatus: [{ type: 'BitstringStatusListCredential', status: 'revoked' }] })
.post('/credentials/status', {
credentialId: 'kj09ij',
credentialStatus: [{ type: 'BitstringStatusListCredential', status: 'revoked' }]
})
.reply(404, { code: 404, message: 'Credential ID not found.' }, [
'X-Powered-By',
'Express',
Expand Down
46 changes: 32 additions & 14 deletions src/test-fixtures/nocks/unprotected_status_signing.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,22 @@ const signedVcWithStatus = {
name: 'Introduction to Computer Science - CS50x'
}
},
credentialStatus: {
id: 'https://jchartrand.github.io/status-test-three/DKSPRCX9WB#1',
type: 'BitstringStatusListEntry',
statusPurpose: 'revocation',
statusListIndex: 1,
statusListCredential: 'https://jchartrand.github.io/status-test-three/DKSPRCX9WB'
},
credentialStatus: [
{
id: 'https://digitalcredentials.github.io/credential-status-jc-test/XA5AAK1PV4#2',
type: 'BitstringStatusListEntry',
statusPurpose: 'revocation',
statusListIndex: 2,
statusListCredential: 'https://digitalcredentials.github.io/credential-status-jc-test/XA5AAK1PV4'
},
{
id: 'https://digitalcredentials.github.io/credential-status-jc-test/DKSPRCX9WB#5',
type: 'BitstringStatusListEntry',
statusPurpose: 'suspension',
statusListIndex: 5,
statusListCredential: 'https://digitalcredentials.github.io/credential-status-jc-test/DKSPRCX9WB'
}
],
proof: {
type: 'Ed25519Signature2020',
created: '2023-08-22T20:11:09Z',
Expand Down Expand Up @@ -139,13 +148,22 @@ const unsignedVcWithStatus = {
name: 'Introduction to Computer Science - CS50x'
}
},
credentialStatus: {
id: 'https://jchartrand.github.io/status-test-three/DKSPRCX9WB#1',
type: 'BitstringStatusListEntry',
statusPurpose: 'revocation',
statusListIndex: 1,
statusListCredential: 'https://jchartrand.github.io/status-test-three/DKSPRCX9WB'
}
credentialStatus: [
{
id: 'https://digitalcredentials.github.io/credential-status-jc-test/XA5AAK1PV4#2',
type: 'BitstringStatusListEntry',
statusPurpose: 'revocation',
statusListIndex: 2,
statusListCredential: 'https://digitalcredentials.github.io/credential-status-jc-test/XA5AAK1PV4'
},
{
id: 'https://digitalcredentials.github.io/credential-status-jc-test/DKSPRCX9WB#5',
type: 'BitstringStatusListEntry',
statusPurpose: 'suspension',
statusListIndex: 5,
statusListCredential: 'https://digitalcredentials.github.io/credential-status-jc-test/DKSPRCX9WB'
}
]
}

export default () => {
Expand Down
Loading

0 comments on commit aecec73

Please sign in to comment.