├── .nvmrc ├── .dockerignore ├── docs ├── OpenCred_Logo.png ├── 02-how-to-use-oidc.md ├── 00-configure-relying-party.md └── 01-how-to-use-api.md ├── test ├── fixtures │ ├── audit │ │ └── vpTokenExample.json │ ├── architecture.png │ ├── submission.json │ ├── revoked-cert │ │ ├── root.cer │ │ ├── intermediate.cer │ │ └── leaf.cer │ ├── expired.badssl.com.cer │ ├── exchange.json │ ├── entra-exchange.json │ ├── vc_jwt.json │ ├── signingKeys.js │ └── oid4vp_jwt.json ├── mock-data.js ├── .eslintrc.cjs ├── utils │ ├── testDocumentLoader.js │ ├── auditVpToken.js │ ├── dids.js │ ├── diVpTokens.js │ ├── credentials.js │ └── jwtVpTokens.js ├── mocha │ ├── 90-utils.test.js │ ├── 100-vc-jwt.test.js │ ├── 60-keygen.test.js │ ├── 20-config.test.js │ ├── 80-translations.test.js │ ├── 40-documentLoader.test.js │ ├── 30-didWeb.test.js │ └── 130-credentialStatus.test.js └── load │ ├── artillery.yaml │ └── presentation.cjs ├── web ├── manifest.json ├── components │ ├── TestPage.vue │ ├── VerificationView.vue │ ├── JsonNode.vue │ ├── YouTubeVideo.vue │ ├── JsonView.vue │ ├── LoginView.vue │ ├── ErrorView.vue │ ├── CountdownDisplay.vue │ ├── TranslateIcon.vue │ ├── ReCaptcha.vue │ ├── CHAPIView.vue │ └── OID4VPView.vue ├── App.vue ├── styles.pcss ├── chapi.js └── index.js ├── configs ├── express.js ├── database.js ├── https-agent.js ├── core.js ├── server.js ├── paths.js ├── authorization.js ├── configUtils.js └── translation.js ├── .editorconfig ├── lib ├── logger.js ├── index.js ├── api.js ├── workflows │ ├── common.js │ ├── vc-api-workflow.js │ └── base.js ├── resolveClient.js ├── callback.js ├── database.js ├── didWeb.js ├── auth.js ├── oidc.js └── audit.js ├── .gitignore ├── test.js ├── tailwind.config.js ├── .github └── workflows │ ├── lint.yaml │ ├── osv-scanner.yaml │ └── packaging.yaml ├── .reuse └── dep5 ├── .eslintrc.cjs ├── Dockerfile ├── common ├── suites.js ├── generateRSA256Key.js ├── generatePrime256v1Key.js ├── jwt.js ├── documentLoader.js ├── zcap.js └── x509.js ├── test.config.js ├── cloudbuild.yaml ├── dev.js ├── LICENSES └── BSD-3-Clause.txt ├── LICENSE └── package.json /.nvmrc: -------------------------------------------------------------------------------- 1 | 20 -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | .env 4 | -------------------------------------------------------------------------------- /docs/OpenCred_Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stateofca/opencred/HEAD/docs/OpenCred_Logo.png -------------------------------------------------------------------------------- /test/fixtures/audit/vpTokenExample.json: -------------------------------------------------------------------------------- 1 | { 2 | "vpToken": "eyJ...", 3 | "fields": {} 4 | } 5 | -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "icons": [], 3 | "name": "OpenCred", 4 | "short_name": "OpenCred" 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stateofca/opencred/HEAD/test/fixtures/architecture.png -------------------------------------------------------------------------------- /configs/express.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | import '@bedrock/express'; 9 | -------------------------------------------------------------------------------- /web/components/TestPage.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 13 | -------------------------------------------------------------------------------- /test/mock-data.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | export const baseUrl = 'http://localhost:22080'; 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.{cjs,js,json,jsonld,mjs,yaml,yml}] 12 | indent_style = space 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /lib/logger.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | import {loggers} from '@bedrock/core'; 9 | 10 | export const logger = loggers.get('app').child('opencred-platform'); 11 | -------------------------------------------------------------------------------- /test/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | module.exports = { 9 | env: { 10 | mocha: true 11 | }, 12 | globals: { 13 | should: true 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.sw[nop] 3 | *~ 4 | .DS_Store 5 | .cache 6 | .env 7 | .nyc_output 8 | .project 9 | .settings 10 | .vscode 11 | 12 | TAGS 13 | coverage 14 | dist 15 | node_modules 16 | package-lock.json 17 | configs/config.yaml 18 | configs/combined.yaml 19 | configs/*.pem 20 | test/fixtures/audit/vpToken.json 21 | 22 | dist 23 | dist-ssr 24 | -------------------------------------------------------------------------------- /configs/database.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | import {config} from '@bedrock/core'; 9 | import '@bedrock/mongodb'; 10 | 11 | // mongodb config 12 | config.mongodb.name = 'opencred_localhost'; 13 | -------------------------------------------------------------------------------- /web/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | 19 | 20 | 22 | -------------------------------------------------------------------------------- /configs/https-agent.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | import {config} from '@bedrock/core'; 9 | import '@bedrock/https-agent'; 10 | 11 | // allow self-signed certificates in dev 12 | config['https-agent'].rejectUnauthorized = false; 13 | -------------------------------------------------------------------------------- /test/utils/testDocumentLoader.js: -------------------------------------------------------------------------------- 1 | import {getDocumentLoader} from '../../common/documentLoader.js'; 2 | 3 | const builder = getDocumentLoader(); 4 | 5 | builder.addStatic( 6 | 'https://www.w3.org/ns/credentials/examples/v2', 7 | { 8 | '@context': { 9 | '@vocab': 'https://www.w3.org/ns/credentials/examples#' 10 | } 11 | }); 12 | 13 | export const documentLoader = builder.build(); 14 | -------------------------------------------------------------------------------- /test/fixtures/submission.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "018815e8-358c-40f2-9648-2edee6908ac4", 3 | "definition_id": "ac1ced75-e910-440d-9c00-a3c0d1dfe379", 4 | "descriptor_map": [ 5 | { 6 | "id": "c65236cb-89a3-4177-8a56-23d239b4f9a8", 7 | "path": "$", 8 | "format": "ldp_vp", 9 | "path_nested": { 10 | "format": "ldp_vc", 11 | "path": "$.verifiableCredential[0]" 12 | } 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /configs/core.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | import {config} from '@bedrock/core'; 9 | 10 | // core configuration 11 | config.core.workers = 1; 12 | config.core.primary.title = 'opencred'; 13 | config.core.worker.title = 'opencred-worker'; 14 | config.core.worker.restart = false; 15 | -------------------------------------------------------------------------------- /web/styles.pcss: -------------------------------------------------------------------------------- 1 | @import "tailwindcss/base"; 2 | @import "tailwindcss/components"; 3 | @import "tailwindcss/utilities"; 4 | 5 | @import url("https://fonts.googleapis.com/css2?family=Source+Serif+4&family=Source+Sans+3&display=swap"); 6 | 7 | body { 8 | font-family: "Source Sans 3", sans-serif; 9 | } 10 | 11 | h1 { 12 | font-family: "Source Serif 4", sans-serif; 13 | } 14 | :root { 15 | --c-overlay-bg: #1e90ff; 16 | --c-white: #ffffff; 17 | } 18 | /* vi: ft=css */ 19 | -------------------------------------------------------------------------------- /configs/server.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | import {config} from '@bedrock/core'; 9 | import '@bedrock/server'; 10 | 11 | // server info 12 | 13 | config.express.httpOnly = true; 14 | config.express.fastifyOptions.trustProxy = true; 15 | config.server.port = 22443; 16 | config.server.httpPort = 22080; 17 | config.server.bindAddr = ['0.0.0.0']; 18 | config.server.domain = 'localhost'; 19 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | import * as bedrock from '@bedrock/core'; 9 | import {fileURLToPath} from 'node:url'; 10 | import path from 'node:path'; 11 | 12 | const {config} = bedrock; 13 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 14 | 15 | config.paths.config = path.join(__dirname, 'configs'); 16 | import './lib/index.js'; 17 | 18 | import '@bedrock/test'; 19 | 20 | bedrock.start(); 21 | -------------------------------------------------------------------------------- /configs/paths.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | import {config} from '@bedrock/core'; 9 | import {fileURLToPath} from 'node:url'; 10 | import os from 'node:os'; 11 | import path from 'node:path'; 12 | 13 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 14 | 15 | // common paths 16 | config.paths.cache = path.join(__dirname, '..', '.cache'); 17 | config.paths.log = path.join(os.tmpdir(), 'localhost-opencred-dev'); 18 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | /* eslint-disable unicorn/prefer-module */ 9 | 10 | import tailwindClipPath from 'tailwind-clip-path'; 11 | /** @type {import('tailwindcss').Config} */ 12 | export default { 13 | content: ['./web/**/*.{html,js,vue}'], 14 | theme: { 15 | extend: {}, 16 | clipPath: { 17 | bg: 'polygon(0 0,100% 0,100% 75%,0 100%)', 18 | }, 19 | }, 20 | plugins: [tailwindClipPath], 21 | }; 22 | -------------------------------------------------------------------------------- /.github/workflows/lint.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2023 - 2024 California Department of Motor Vehicles 2 | # Copyright 2023 - 2024 Digital Bazaar, Inc. 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | 6 | name: Lint 7 | 8 | on: [push] 9 | 10 | jobs: 11 | lint: 12 | runs-on: ubuntu-latest 13 | timeout-minutes: 10 14 | strategy: 15 | matrix: 16 | node-version: [20.x] 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Use Node.js ${{ matrix.node-version }} 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | - run: npm install 24 | - name: Run eslint 25 | run: npm run lint 26 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | import '@bedrock/core'; 9 | 10 | import '@bedrock/express'; 11 | import '@bedrock/views'; 12 | import '@bedrock/webpack'; 13 | import '@bedrock/health'; 14 | import '@bedrock/express-browser-fixes'; 15 | import '@bedrock/health'; 16 | import '@bedrock/server'; 17 | 18 | // validate and load config 19 | import '../configs/config.js'; 20 | 21 | import './api.js'; 22 | import './http.js'; 23 | import './database.js'; 24 | 25 | // this should always be the last import 26 | import '@bedrock/config-yaml'; 27 | -------------------------------------------------------------------------------- /.reuse/dep5: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Contact: Digital Bazaar, Inc. 3 | 4 | Files: *.md .dockerignore .editorconfig .gitignore .nvmrc package.json 5 | test/fixtures/expired.badssl.com.cer test/fixtures/oid4vp_di.json 6 | test/fixtures/oid4vp_jwt.json test/fixtures/revoked-cert/intermediate.cer 7 | test/fixtures/revoked-cert/leaf.cer test/fixtures/revoked-cert/root.cer 8 | test/fixtures/signingKeys.js test/fixtures/submission.json 9 | test/fixtures/vc_jwt.json web/manifest.json web/styles.pcss 10 | Copyright: 2023-2024 California Department of Motor Vehicles 11 | 2023-2024 Digital Bazaar, Inc. 12 | License: BSD-3-Clause 13 | -------------------------------------------------------------------------------- /web/components/VerificationView.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | 24 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2023 - 2024 California Department of Motor Vehicles 3 | * Copyright 2023 - 2024 Digital Bazaar, Inc. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | module.exports = { 9 | root: true, 10 | env: { 11 | node: true 12 | }, 13 | extends: [ 14 | 'plugin:quasar/standard', 15 | 'digitalbazaar', 16 | 'digitalbazaar/module', 17 | 'digitalbazaar/vue3' 18 | ], 19 | ignorePatterns: [ 20 | 'node_modules/', 21 | 'dist/' 22 | ], 23 | rules: { 24 | 'linebreak-style': [ 25 | 'error', 26 | (process.platform === 'win32' ? 'windows' : 'unix') 27 | ], 28 | 'unicorn/prefer-node-protocol': 'error', 29 | 'vue/no-v-html': 'off' 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /test/utils/auditVpToken.js: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs'; 2 | import {httpClient} from '@digitalbazaar/http-client'; 3 | 4 | const main = async () => { 5 | const domain = process.argv[2]; 6 | const url = `${domain}/audit-presentation`; 7 | const vpTokenData = JSON.parse(fs.readFileSync( 8 | './test/fixtures/audit/vpToken.json' 9 | )); 10 | const headers = {'Content-Type': 'application/json'}; 11 | httpClient.extend({headers}); 12 | 13 | let auditResponse; 14 | try { 15 | const response = 16 | await httpClient.post(url, {json: vpTokenData}); 17 | auditResponse = response; 18 | } catch(error) { 19 | auditResponse = error; 20 | } 21 | 22 | console.log(JSON.stringify(auditResponse.data, null, 2)); 23 | }; 24 | 25 | main(); 26 | -------------------------------------------------------------------------------- /web/components/JsonNode.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 19 | 20 | 36 | -------------------------------------------------------------------------------- /web/components/YouTubeVideo.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 23 | 24 |