Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ charset = utf-8
insert_final_newline = true
trim_trailing_whitespace = true

[{*.{Dockerfile,js,jsx,ts,tsx},Dockerfile}]
[{*.{Dockerfile,js,jsx,mjs,ts,tsx},Dockerfile}]
indent_style = tab

[public/styles/**.css]
Expand Down
5 changes: 2 additions & 3 deletions .editorconfig-checker.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"Exclude": [
"^(node_modules|dist|build)/"
]
"SpacesAfterTabs": true,
"Exclude": ["^(node_modules|dist|build)/"]
}
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ body:
id: to-reproduce
attributes:
label: To Reproduce
description: "Steps to reproduce the behavior"
description: 'Steps to reproduce the behavior'
value: |
1. Go to '...'
2. Click on '....'
Expand Down
8 changes: 4 additions & 4 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ body:
id: problem-statement
attributes:
label: Problem Statement
description: "A clear and concise description of the problem or need you want this feature to address."
description: 'A clear and concise description of the problem or need you want this feature to address.'
validations:
required: true
required: true

- type: textarea
id: proposed-solution
attributes:
label: Proposed Solution
description: "The solution you propose to address the problem."
description: 'The solution you propose to address the problem.'
placeholder: |
Describe your suggested solution in detail. Be sure to include:
* The technical implementation and any key considerations.
Expand All @@ -26,7 +26,7 @@ body:
id: additional-information
attributes:
label: Additional Information
description: "Any other relevant details, such as context, screenshots, external references, or links to related issues or discussions."
description: 'Any other relevant details, such as context, screenshots, external references, or links to related issues or discussions.'

- type: markdown
attributes:
Expand Down
45 changes: 37 additions & 8 deletions .github/workflows/code-formatting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,42 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Check out code
uses: actions/checkout@v7
- name: Check out code
uses: actions/checkout@v7

- name: Set up editorconfig-checker
uses: editorconfig-checker/action-editorconfig-checker@v3.0.0
with:
version: v4.0.2
- name: Set up editorconfig-checker
uses: editorconfig-checker/action-editorconfig-checker@v3.0.0
with:
version: v4.0.2

- name: Check code formatting
run: editorconfig-checker -no-color
- name: Check code formatting
run: editorconfig-checker -no-color

prettier-eslint:
name: Check Prettier and ESLint

runs-on: ubuntu-latest

permissions:
contents: read

steps:
- name: Check out code
uses: actions/checkout@v7

- name: Set up Node.js
uses: actions/setup-node@v7
with:
node-version: 24
cache: yarn

- name: Install dependencies
env:
YARN_NETWORK_CONCURRENCY: '1'
run: yarn install --frozen-lockfile

- name: Check Prettier formatting
run: yarn format:check

- name: Check ESLint rules
run: yarn lint
5 changes: 2 additions & 3 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ concurrency:

jobs:
build:

# Permissions for GITHUB_TOKEN
permissions:
contents: read # To check out repo
packages: read # To read NPM registry
contents: read # To check out repo
packages: read # To read NPM registry

uses: wwwallet/wwwallet/.github/workflows/docker-build-push.yml@master
secrets: inherit
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/docker-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ on:
- v1.*
- v2.*


jobs:
build:

# Permissions for GITHUB_TOKEN
permissions:
contents: read # To check out repo
contents: read # To check out repo
packages: write # To read NPM registry and push Docker image

uses: wwwallet/wwwallet/.github/workflows/docker-build-push.yml@master
Expand Down
16 changes: 15 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,19 @@ repos:
hooks:
- id: editorconfig-checker
name: Check .editorconfig rules
args: ["-no-color"]
args: ['-no-color']
types_or: [text]

- repo: local
hooks:
- id: prettier
name: Check Prettier formatting
entry: yarn format:check
language: system
pass_filenames: false

- id: eslint
name: Check ESLint rules
entry: yarn lint
language: system
pass_filenames: false
3 changes: 3 additions & 0 deletions .prettierrc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
singleQuote: true
trailingComma: 'all'
printWidth: 100
43 changes: 23 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# wwWallet Verifier

wwWallet Verifier is a standalone digital credential verifier implementing OpenID4VP.

> [!NOTE]
Expand All @@ -7,11 +8,13 @@ wwWallet Verifier is a standalone digital credential verifier implementing OpenI
## How to run

Install dependencies

```
yarn install
```

Run in dev mode

```
yarn run dev
```
Expand All @@ -24,26 +27,26 @@ The verifier also expects a root CA certificate at `keys/ca.crt`, used as a trus

Environment variables and how they are used:

| Variable | Purpose | Default / Notes |
| --- | --- | --- |
| `SERVICE_URL` | Full external URL of the verifier. | Default: `http://localhost:8005`. Used as the OpenID4VP client base URL, for the `direct_post` response URI and for callback URLs. |
| `SERVICE_PORT` | Port the HTTP server listens on. | Default: `8005`. |
| `APP_SECRET` | Secret used to sign the Express session cookie. | Has an insecure built-in default. Change it outside local development. |
| `WWWALLET_URL` | wwWallet frontend URL that authorization requests are sent to. | Default: `http://localhost:3000/cb`. |
| `DB_HOST` | MySQL/MariaDB host. | Default: `127.0.0.1`. |
| `DB_PORT` | MySQL/MariaDB port. | Default: `3307`. |
| `DB_USERNAME` | Database user. | Default: `root`. |
| `DB_PASSWORD` | Database password. | Default: `root`. |
| `DB_NAME` | Database name. | Default: `verifier`. |
| `PRESENTATION_FLOW_RESPONSE_MODE` | OpenID4VP `response_mode` used in authorization requests. | Default: `direct_post.jwt`. Supported values: `direct_post`, `direct_post.jwt`. |
| `TRUSTED_ISSUERS` | Comma-separated list of credential issuer identifiers whose certificates are added as trusted roots. | Default: `http://localhost:8003/openid`. For each issuer, the verifier fetches `/.well-known/openid-credential-issuer` and, if it has an `mdoc_iacas_uri`, trusts the certificates listed there (relevant for mso_mdoc). |
| `CLOCK_TOLERANCE` | Allowed clock skew (seconds) when validating credential and presentation timestamps. | Default: `60`. |
| `SESSION_ID_COOKIE_MAX_AGE` | Max age (milliseconds) of the `session_id` cookie. | Default: `900000` (15 minutes). |
| `SESSION_ID_COOKIE_SECURE` | Set the `Secure` flag on the `session_id` cookie. | Default: `false`. Only the exact value `true` enables it. Set it when served over HTTPS. |
| `SITE_NAME` | Web app manifest `name`. | Default: `wwWallet Verifier`. |
| `SITE_SHORT_NAME` | Web app manifest `short_name`. | Default: `wwWallet Verifier`. |
| `SITE_THEME_COLOR` | Web app manifest `theme_color`. | Default: `#4d7e3e`. Quote hex values in `.env` (`"#4d7e3e"`), otherwise `#` starts a comment. |
| `SITE_BACKGROUND_COLOR` | Web app manifest `background_color`. | Default: `#4d7e3e`. Quote hex values in `.env` (`"#4d7e3e"`), otherwise `#` starts a comment. |
| Variable | Purpose | Default / Notes |
| --------------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `SERVICE_URL` | Full external URL of the verifier. | Default: `http://localhost:8005`. Used as the OpenID4VP client base URL, for the `direct_post` response URI and for callback URLs. |
| `SERVICE_PORT` | Port the HTTP server listens on. | Default: `8005`. |
| `APP_SECRET` | Secret used to sign the Express session cookie. | Has an insecure built-in default. Change it outside local development. |
| `WWWALLET_URL` | wwWallet frontend URL that authorization requests are sent to. | Default: `http://localhost:3000/cb`. |
| `DB_HOST` | MySQL/MariaDB host. | Default: `127.0.0.1`. |
| `DB_PORT` | MySQL/MariaDB port. | Default: `3307`. |
| `DB_USERNAME` | Database user. | Default: `root`. |
| `DB_PASSWORD` | Database password. | Default: `root`. |
| `DB_NAME` | Database name. | Default: `verifier`. |
| `PRESENTATION_FLOW_RESPONSE_MODE` | OpenID4VP `response_mode` used in authorization requests. | Default: `direct_post.jwt`. Supported values: `direct_post`, `direct_post.jwt`. |
| `TRUSTED_ISSUERS` | Comma-separated list of credential issuer identifiers whose certificates are added as trusted roots. | Default: `http://localhost:8003/openid`. For each issuer, the verifier fetches `/.well-known/openid-credential-issuer` and, if it has an `mdoc_iacas_uri`, trusts the certificates listed there (relevant for mso_mdoc). |
| `CLOCK_TOLERANCE` | Allowed clock skew (seconds) when validating credential and presentation timestamps. | Default: `60`. |
| `SESSION_ID_COOKIE_MAX_AGE` | Max age (milliseconds) of the `session_id` cookie. | Default: `900000` (15 minutes). |
| `SESSION_ID_COOKIE_SECURE` | Set the `Secure` flag on the `session_id` cookie. | Default: `false`. Only the exact value `true` enables it. Set it when served over HTTPS. |
| `SITE_NAME` | Web app manifest `name`. | Default: `wwWallet Verifier`. |
| `SITE_SHORT_NAME` | Web app manifest `short_name`. | Default: `wwWallet Verifier`. |
| `SITE_THEME_COLOR` | Web app manifest `theme_color`. | Default: `#4d7e3e`. Quote hex values in `.env` (`"#4d7e3e"`), otherwise `#` starts a comment. |
| `SITE_BACKGROUND_COLOR` | Web app manifest `background_color`. | Default: `#4d7e3e`. Quote hex values in `.env` (`"#4d7e3e"`), otherwise `#` starts a comment. |

## Pre-commit

Expand Down
44 changes: 23 additions & 21 deletions config/index.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,41 @@
import fs from "node:fs";
import path from "node:path";
import fs from 'node:fs';
import path from 'node:path';
import dotenv from 'dotenv';
dotenv.config();

const ROOT_CA_PATH = path.resolve(process.cwd(), "./keys/ca.crt");
const rootCa = fs.readFileSync(ROOT_CA_PATH, "utf8");
const ROOT_CA_PATH = path.resolve(process.cwd(), './keys/ca.crt');
const rootCa = fs.readFileSync(ROOT_CA_PATH, 'utf8');

export const config = {
url: String(process.env.SERVICE_URL || "http://localhost:8005"),
port: parseInt(process.env.SERVICE_PORT || "8005"),
appSecret: String(process.env.APP_SECRET || "dsfkwfkwfwdfdsfSaSe2e34r4frwr42rAFdsf2lfmfsmklfwmer"),
url: String(process.env.SERVICE_URL || 'http://localhost:8005'),
port: parseInt(process.env.SERVICE_PORT || '8005'),
appSecret: String(
process.env.APP_SECRET || 'dsfkwfkwfwdfdsfSaSe2e34r4frwr42rAFdsf2lfmfsmklfwmer',
),
db: {
host: String(process.env.DB_HOST || "127.0.0.1"),
port: String(process.env.DB_PORT || "3307"),
username: String(process.env.DB_USERNAME || "root"),
password: String(process.env.DB_PASSWORD || "root"),
dbname: String(process.env.DB_NAME || "verifier"),
host: String(process.env.DB_HOST || '127.0.0.1'),
port: String(process.env.DB_PORT || '3307'),
username: String(process.env.DB_USERNAME || 'root'),
password: String(process.env.DB_PASSWORD || 'root'),
dbname: String(process.env.DB_NAME || 'verifier'),
},
presentationFlow: {
response_mode: String(process.env.PRESENTATION_FLOW_RESPONSE_MODE || "direct_post.jwt"),
response_mode: String(process.env.PRESENTATION_FLOW_RESPONSE_MODE || 'direct_post.jwt'),
},
wwwalletURL: process.env.WWWALLET_URL || "http://localhost:3000/cb",
wwwalletURL: process.env.WWWALLET_URL || 'http://localhost:3000/cb',
trustedRootCertificates: [rootCa],
trustedIssuers: process.env.TRUSTED_ISSUERS
? process.env.TRUSTED_ISSUERS.split(',')
: ["http://localhost:8003/openid"],
: ['http://localhost:8003/openid'],
sessionIdCookieConfiguration: {
maxAge: parseInt(process.env.SESSION_ID_COOKIE_MAX_AGE || "900000", 10),
maxAge: parseInt(process.env.SESSION_ID_COOKIE_MAX_AGE || '900000', 10),
secure: process.env.SESSION_ID_COOKIE_SECURE === 'true' ? true : false,
},
clockTolerance: parseInt(process.env.CLOCK_TOLERANCE || "60", 10),
clockTolerance: parseInt(process.env.CLOCK_TOLERANCE || '60', 10),
siteConfig: {
name: process.env.SITE_NAME || "wwWallet Verifier",
short_name: process.env.SITE_SHORT_NAME || "wwWallet Verifier",
theme_color: process.env.SITE_THEME_COLOR || "#4d7e3e",
background_color: process.env.SITE_BACKGROUND_COLOR || "#4d7e3e",
name: process.env.SITE_NAME || 'wwWallet Verifier',
short_name: process.env.SITE_SHORT_NAME || 'wwWallet Verifier',
theme_color: process.env.SITE_THEME_COLOR || '#4d7e3e',
background_color: process.env.SITE_BACKGROUND_COLOR || '#4d7e3e',
},
};
Loading
Loading