Skip to content

Commit

Permalink
Merge pull request #23 from cre8/cre8/issue21
Browse files Browse the repository at this point in the history
Add demo pages for issuer and verifier
  • Loading branch information
cre8 authored May 3, 2024
2 parents 756a0f5 + ef0a6a8 commit 568118a
Show file tree
Hide file tree
Showing 24 changed files with 586 additions and 16 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
/**/node_modules
.git
.gitignore
*.md
Expand Down
22 changes: 9 additions & 13 deletions apps/holder/projects/pwa/src/app/scanner/scanner.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,24 +97,19 @@ export class ScannerComponent implements OnInit, OnDestroy {
this.scanner = new Html5Qrcode('reader');
const width = window.innerWidth;
const height = window.innerHeight;
// const aspectRatio = width / height;
const reverseAspectRatio = height / width;

// const mobileAspectRatio =
// reverseAspectRatio > 1.5
// ? reverseAspectRatio + (reverseAspectRatio * 12) / 100
// : reverseAspectRatio;
await this.scanner.start(
{ deviceId: { exact: this.selectedDevice } },
{
fps: 10,
qrbox: { width: 300, height: 300 },
//TODO: the ratio is not perfect yet
aspectRatio: reverseAspectRatio,
},
this.onScanSuccess,
this.onScanSuccess.bind(this),
// we do nothing when a scan failed
() => {}
(err) => {
// console.log(err);
}
);
}

Expand All @@ -132,17 +127,18 @@ export class ScannerComponent implements OnInit, OnDestroy {
* Handle the scan success
* @param decodedText
*/
onScanSuccess(decodedText: string) {
async onScanSuccess(decodedText: string) {
console.log(decodedText);
// handle the scanned code as you like, for example:
if (decodedText.startsWith('openid-credential-offer://')) {
this.showRequest(decodedText, 'receive');
// use a constant for the verification schema
this.scanner?.stop();
await this.scanner?.stop();
} else if (decodedText.startsWith('openid://')) {
this.showRequest(decodedText, 'send');
this.scanner?.stop();
await this.scanner?.stop();
} else {
alert("Scanned text doesn't match the expected format");
alert('Scanned text: ' + decodedText);
}
}

Expand Down
24 changes: 24 additions & 0 deletions apps/issuer-demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
31 changes: 31 additions & 0 deletions apps/issuer-demo/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
FROM node:20-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

FROM base AS build
# the downside of this is that is can not cache the node_modules since a change to all elements will trigger a cache invalidation
COPY . /usr/src/app
WORKDIR /usr/src/app
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
# build the project
RUN pnpm --filter=issuer-demo run build
# deploy the project
RUN pnpm deploy --filter=issuer-demo --prod /app

FROM georgjung/nginx-brotli:1.23.3
WORKDIR /usr/share/nginx/html
RUN mkdir -p /etc/nginx && \
echo 'events {}' > /etc/nginx/nginx.conf && \
echo 'http {' >> /etc/nginx/nginx.conf && \
echo ' include /etc/nginx/mime.types;' >> /etc/nginx/nginx.conf && \
echo ' server {' >> /etc/nginx/nginx.conf && \
echo ' listen 80;' >> /etc/nginx/nginx.conf && \
echo ' root /usr/share/nginx/html;' >> /etc/nginx/nginx.conf && \
echo ' index index.html;' >> /etc/nginx/nginx.conf && \
echo ' location / {' >> /etc/nginx/nginx.conf && \
echo ' try_files $uri $uri/ /index.html =404;' >> /etc/nginx/nginx.conf && \
echo ' }' >> /etc/nginx/nginx.conf && \
echo ' }' >> /etc/nginx/nginx.conf && \
echo '}' >> /etc/nginx/nginx.conf
COPY --from=build /usr/src/app/apps/issuer-demo/dist .
12 changes: 12 additions & 0 deletions apps/issuer-demo/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Issuer Demo</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
23 changes: 23 additions & 0 deletions apps/issuer-demo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "issuer-demo",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"clean": "rm -rf dist && rm -rf node_modules",
"lint": "biome lint .",
"format": "biome check --apply .",
"publish": "pnpm run build && cd ../../ && docker compose build issuer-demo && docker compose push issuer-demo"
},
"devDependencies": {
"@types/qrcode": "^1.5.5",
"typescript": "^5.2.2",
"vite": "^5.2.0"
},
"dependencies": {
"qrcode": "^1.5.3"
}
}
4 changes: 4 additions & 0 deletions apps/issuer-demo/public/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"issuerUrl": "http://localhost:3001",
"credentialId": "Identity"
}
75 changes: 75 additions & 0 deletions apps/issuer-demo/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import './style.css';
import qrcode from 'qrcode';

interface RequestLinkBody {
credentialSubject?: Record<string, unknown>;
credentialId: string;
pin?: boolean;
}

interface Config {
issuerUrl: string;
credentialId: string;
}

let config: Config;

//fetch the config
fetch('/config.json')
.then((res) => res.json())
.then((res) => {
config = res;
});

let loop: NodeJS.Timeout;

function getCode() {
if (loop) {
clearInterval(loop);
}
const body: RequestLinkBody = {
credentialId: config.credentialId,
};
fetch(`${config.issuerUrl}/request`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
})
.then((res) => res.json())
.then((res) => {
//display the qrocde
qrcode
.toDataURL(res.uri)
.then((url) =>
(document.getElementById('qr') as HTMLElement).setAttribute(
'src',
url
)
);
getStatus(res.session.preAuthorizedCode);
//request for the status update in the background with a loop
loop = setInterval(() => getStatus(res.session.preAuthorizedCode), 2000);
});
}

function getStatus(id: string) {
fetch(`${config.issuerUrl}/sessions/${id}`)
.then((res) => res.json())
.then((res) => {
console.log(res);
status.innerHTML = res.status;
});
}

(document.querySelector<HTMLDivElement>('#app') as HTMLDivElement).innerHTML = `
<button id="get">Get Code</button>
<img id="qr" />
<div id="status"></div>
`;
const status = document.getElementById('status') as HTMLDivElement;
(document.getElementById('get') as HTMLElement).addEventListener(
'click',
getCode
);
Empty file added apps/issuer-demo/src/style.css
Empty file.
23 changes: 23 additions & 0 deletions apps/issuer-demo/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,

/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,

/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}
20 changes: 17 additions & 3 deletions apps/issuer/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,13 @@ vcIssuerServer.router.post('/request', async (req, res) => {
surname: 'Mustermann',
};
const credentialId = values.credentialId;
const sessionId = v4();
try {
const response = await vcIssuer.createCredentialOfferURI({
credentials: [issuer.getCredential(credentialId).id as string],
grants: {
'urn:ietf:params:oauth:grant-type:pre-authorized_code': {
'pre-authorized_code': v4().substring(0, 10),
'pre-authorized_code': sessionId,
user_pin_required: values.pin,
},
},
Expand All @@ -192,11 +193,21 @@ vcIssuerServer.router.post('/request', async (req, res) => {
});
//we are returning the response to the client
res.send(response);
} catch (error) {
res.status(422).send();
} catch (error: any) {
res.status(422).send(error.message);
}
});

expressSupport.express.get('/sessions/:id', async (req, res) => {
const id = req.params.id;
const session = await vcIssuer.credentialOfferSessions.get(id);
if (!session) {
res.status(404).json({ error: 'Session not found' });
return;
}
res.send(session);
});

/**
* Returns the issuers metadata.
*/
Expand All @@ -210,6 +221,9 @@ expressSupport.express.get('/.well-known/jwt-vc-issuer', async (req, res) => {
res.send(metadata);
});

/**
* Health check route.
*/
expressSupport.express.get('/health', async (req, res) => {
res.send('ok');
});
Expand Down
24 changes: 24 additions & 0 deletions apps/verifier-demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
31 changes: 31 additions & 0 deletions apps/verifier-demo/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
FROM node:20-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

FROM base AS build
# the downside of this is that is can not cache the node_modules since a change to all elements will trigger a cache invalidation
COPY . /usr/src/app
WORKDIR /usr/src/app
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
# build the project
RUN pnpm --filter=verifier-demo run build
# deploy the project
RUN pnpm deploy --filter=verifier-demo --prod /app

FROM georgjung/nginx-brotli:1.23.3
WORKDIR /usr/share/nginx/html
RUN mkdir -p /etc/nginx && \
echo 'events {}' > /etc/nginx/nginx.conf && \
echo 'http {' >> /etc/nginx/nginx.conf && \
echo ' include /etc/nginx/mime.types;' >> /etc/nginx/nginx.conf && \
echo ' server {' >> /etc/nginx/nginx.conf && \
echo ' listen 80;' >> /etc/nginx/nginx.conf && \
echo ' root /usr/share/nginx/html;' >> /etc/nginx/nginx.conf && \
echo ' index index.html;' >> /etc/nginx/nginx.conf && \
echo ' location / {' >> /etc/nginx/nginx.conf && \
echo ' try_files $uri $uri/ /index.html =404;' >> /etc/nginx/nginx.conf && \
echo ' }' >> /etc/nginx/nginx.conf && \
echo ' }' >> /etc/nginx/nginx.conf && \
echo '}' >> /etc/nginx/nginx.conf
COPY --from=build /usr/src/app/apps/verifier-demo/dist .
12 changes: 12 additions & 0 deletions apps/verifier-demo/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Verifier Demo</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
23 changes: 23 additions & 0 deletions apps/verifier-demo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "verifier-demo",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"clean": "rm -rf dist && rm -rf node_modules",
"lint": "biome lint .",
"format": "biome check --apply .",
"publish": "pnpm run build && cd ../../ && docker compose build verifier-demo && docker compose push verifier-demo"
},
"devDependencies": {
"@types/qrcode": "^1.5.5",
"typescript": "^5.2.2",
"vite": "^5.2.0"
},
"dependencies": {
"qrcode": "^1.5.3"
}
}
Loading

0 comments on commit 568118a

Please sign in to comment.