{"id":51055855,"url":"https://github.com/cyr-ius/verifid","last_synced_at":"2026-06-22T21:01:36.369Z","repository":{"id":349229952,"uuid":"1201499252","full_name":"cyr-ius/verifid","owner":"cyr-ius","description":"VerifID is a self-hosted employee identity verification portal powered by Microsoft Entra Verified ID. It enables HR teams to issue verifiable credentials to employees and helpdesk agents to verify employee identities without passwords — using a QR code and Microsoft Authenticator.","archived":false,"fork":false,"pushed_at":"2026-06-15T21:41:19.000Z","size":1735,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-15T23:22:23.298Z","etag":null,"topics":["control","cybersecurity","detection","id","identity","microsoft","verified"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cyr-ius.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"cyr-ius"}},"created_at":"2026-04-04T19:00:21.000Z","updated_at":"2026-06-15T21:41:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cyr-ius/verifid","commit_stats":null,"previous_names":["cyr-ius/verifid"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/cyr-ius/verifid","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cyr-ius%2Fverifid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cyr-ius%2Fverifid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cyr-ius%2Fverifid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cyr-ius%2Fverifid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cyr-ius","download_url":"https://codeload.github.com/cyr-ius/verifid/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cyr-ius%2Fverifid/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34665261,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-22T02:00:06.391Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["control","cybersecurity","detection","id","identity","microsoft","verified"],"created_at":"2026-06-22T21:01:30.791Z","updated_at":"2026-06-22T21:01:36.354Z","avatar_url":"https://github.com/cyr-ius.png","language":"TypeScript","funding_links":["https://github.com/sponsors/cyr-ius"],"categories":[],"sub_categories":[],"readme":"# 🛡️ VerifID\n\n**VerifID** is a contact verification portal based on **Microsoft Entra Verified ID**.\n\n\u003cimg width=\"916\" height=\"157\" alt=\"image\" src=\"https://github.com/user-attachments/assets/6cad31dd-1882-40f8-bb40-15fca81b5c96\" /\u003e\n\nIt allows HR teams to provide verifiable credentials to employees. It also provides support teams with a way to verify their identity without a password, using a QR code and Microsoft Authenticator.\n\nThe goal is to limit identity theft and fraud.\n\nMicrosoft Verified ID provides:\n\n- Digital fingerprint generation via the \"My account\" page\n- Digital fingerprint creation and verification APIs\n\nThis development offers a user-friendly interface focused on verifying the identity of the person you are interacting with.\n\n[Verified ID](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-verified-id) For more information, you can visit the Microsoft website.\n\nThe development carried out is based on the examples provided by Microsoft in the [Azure-Samples repository](https://github.com/Azure-Samples/active-directory-verifiable-credentials)\n\n---\n\n## Table of Contents\n\n- [Features](#features)\n- [Screenshots](#screenshots)\n- [Architecture](#architecture)\n- [Prerequisites](#prerequisites)\n- [Quick Start](#quick-start)\n- [Flows](#flows)\n- [Environment Variables](#environment-variables)\n- [Azure App Registrations](#azure-app-registrations)\n  - [App 1 — Backend API App Registration](#app-1--backend-api-app-registration)\n  - [App 2 — Frontend SPA App Registration](#app-2--frontend-spa-app-registration)\n  - [Summary Table](#summary-table)\n- [Roles \u0026 Permissions](#roles--permissions)\n- [Development](#development)\n- [CI / CD](#ci--cd)\n- [License](#license)\n\n---\n\n## Features\n\n- 🪪 **Credential Issuance** — HR issues a `VerifiedEmployee` verifiable credential directly into the employee's Microsoft Authenticator wallet\n- 🔍 **Identity Verification** — Helpdesk agents generate a QR code; the employee scans it to prove their identity in seconds\n- 📟 **Assistance Code** — A short 4-digit code shared verbally with the helpdesk to look up a verification result without needing a session ID\n- 🔐 **Azure Entra ID authentication** — Optional JWT-based access control with role and scope enforcement (`helpdesk`, `hr`)\n- 📱 **Mobile-first UI** — Responsive Angular 21 frontend, installable as a PWA\n- 🐳 **Single-container deployment** — Frontend and backend bundled in one Docker image\n- 🔒 **Security headers** — CSP, HSTS, X-Frame-Options, Permissions-Policy applied on every response\n\n---\n\n## Screenshot\n\n### Identity check (person being checked)\n\n\u003cimg width=\"1141\" height=\"663\" alt=\"image\" src=\"https://github.com/user-attachments/assets/32e36d26-e20b-400d-998d-f2b2eaafe190\" /\u003e\n\u003cimg width=\"1354\" height=\"695\" alt=\"image\" src=\"https://github.com/user-attachments/assets/ee458734-5745-4a42-bbda-aa3c3e62baa3\" /\u003e\n\u003cimg width=\"1348\" height=\"535\" alt=\"image\" src=\"https://github.com/user-attachments/assets/54ea8564-674a-4f46-80e5-fec13f711811\" /\u003e\n\n### Identity check (person performing the check)\n\n\u003cimg width=\"1371\" height=\"606\" alt=\"image\" src=\"https://github.com/user-attachments/assets/1adc7064-5dd0-4efe-b563-d1328af3979b\" /\u003e\n\u003cimg width=\"1348\" height=\"535\" alt=\"image\" src=\"https://github.com/user-attachments/assets/bc12ae8f-741f-4655-9198-0790d06ba395\" /\u003e\n\n## Architecture\n\n| Layer          | Technology                                                          |\n| -------------- | ------------------------------------------------------------------- |\n| **Frontend**   | Angular 21 — Signals, Signal Forms, Zoneless, Standalone Components |\n| **Styling**    | Bootstrap 5.3 + Bootstrap Icons 1.13                                |\n| **Backend**    | FastAPI 0.135 + Python 3.14 (fully async)                           |\n| **Validation** | Pydantic v2                                                         |\n| **Identity**   | Microsoft Entra Verified ID (Request Service API)                   |\n| **Auth**       | MSAL (frontend) + python-jose JWT validation (backend)              |\n| **Container**  | Single-stage Docker image — `python:3.14-alpine`                    |\n\n```\n┌─────────────────────────────────────────────┐\n│              Docker Container               │\n│                                             │\n│  ┌──────────────┐   ┌─────────────────────┐ │\n│  │   Angular    │   │      FastAPI        │ │\n│  │  (static     │◄──│   /api/v1/...       │ │\n│  │   files)     │   │                     │ │\n│  └──────────────┘   └────────┬────────────┘ │\n└───────────────────────────────┼─────────────┘\n                                │\n              ┌─────────────────▼──────────────┐\n              │  Microsoft Entra Verified ID   │\n              │  (verifiedid.did.msidentity.com)│\n              └────────────────────────────────┘\n```\n\n---\n\n## Prerequisites\n\n- Docker 24+ (or compatible runtime)\n- Docker Compose v2 _(optional)_\n- A Microsoft Azure tenant with:\n  - Microsoft Entra Verified ID enabled and configured\n  - Two App Registrations (see [Azure App Registrations](#azure-app-registrations))\n  - A published `VerifiedEmployee` credential type\n\n---\n\n## Quick Start\n\n### Docker CLI\n\n```bash\ndocker run -d \\\n  --name verifid \\\n  -p 8080:8080 \\\n  -e AZURE_TENANT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \\\n  -e AZURE_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \\\n  -e AZURE_CLIENT_SECRET=your-client-secret \\\n  -e VERIFIED_ID_DID=did:web:yourdomain.com \\\n  -e VERIFIED_ID_CONTRACT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \\\n  -e APP_BASE_URL=https://yourdomain.com \\\n  -e API_KEY=your-api-key \\\n  -e AUTH_CLIENT_ID=xxxxxxx-xxx-xxxx-xxxx-xxxxxxxxxxxx \\\n  ghcr.io/cyr-ius/verifid:latest\n```\n\nOpen **http://localhost:8000** to access the portal.\n\n### Docker Compose\n\n```yaml\nservices:\n  verifid:\n    image: ghcr.io/cyr-ius/verifid:latest\n    container_name: verifid\n    restart: unless-stopped\n    ports:\n      - \"8080:8080\"\n    environment:\n      - AZURE_TENANT_ID=${AZURE_TENANT_ID}\n      - AZURE_CLIENT_ID=${AZURE_CLIENT_ID}\n      - AZURE_CLIENT_SECRET=${AZURE_CLIENT_SECRET}\n      - VERIFIED_ID_DID=${VERIFIED_ID_DID}\n      - VERIFIED_ID_CONTRACT_ID=${VERIFIED_ID_CONTRACT_ID}\n      - APP_BASE_URL=${APP_BASE_URL}\n      - API_KEY=${API_KEY}\n      - AUTH_CLIENT_ID=${AUTH_CLIENT_ID}\n```\n\nThen create a `.env` file from the provided example:\n\n```bash\ncp backend/.env.example .env\n# Edit .env with your actual values\ndocker compose up -d\n```\n\n---\n\n## Flows\n\n### Verification (Helpdesk)\n\n1. The helpdesk agent opens **`/verify`** and clicks **Start verification**\n2. VerifID calls the Verified ID Request Service and generates a QR code\n3. A **4-digit assistance code** is displayed prominently — the employee communicates it verbally to the agent\n4. The employee scans the QR code with **Microsoft Authenticator** and confirms credential sharing\n5. The helpdesk UI polls until the credential is verified and displays the employee's claims\n6. Alternatively, the agent can look up the result later via the **`/assist`** dashboard using the assistance code\n\n### Issuance (HR)\n\n1. An HR agent opens **`/issue`** (requires `hr` role)\n2. They fill in the employee's details: name, employee ID, job title, department\n3. VerifID generates a QR code — the employee scans it with Microsoft Authenticator\n4. The `VerifiedEmployee` credential is stored in the employee's wallet, ready to be presented to the helpdesk\n\n---\n\n## Environment Variables\n\n### Required\n\n| Variable                  | Description                                                                    |\n| ------------------------- | ------------------------------------------------------------------------------ |\n| `AZURE_TENANT_ID`         | Azure Active Directory tenant ID                                               |\n| `AZURE_CLIENT_ID`         | Client ID of the **Backend API** app registration (Verif ID API interface)     |\n| `AZURE_CLIENT_SECRET`     | Client secret for the backend app registration                                 |\n| `VERIFIED_ID_DID`         | Your Verified ID authority DID (e.g. `did:web:yourdomain.com`)                 |\n| `VERIFIED_ID_CONTRACT_ID` | Credential contract ID used to build the Verified ID issuance manifest URL     |\n| `APP_BASE_URL`            | Public HTTPS base URL of the application — used by Microsoft to POST callbacks |\n| `API_KEY`                 | Shared secret that Microsoft must include in callback headers                  |\n| `AUTH_CLIENT_ID`          | Client ID of the **Frontend SPA** app registration (Verif ID interface)        |\n\n### Authentication\n\n| Variable                        | Description                                      | Default           |\n| ------------------------------- | ------------------------------------------------ | ----------------- |\n| `AUTH_ENABLED`                  | Enable JWT authentication on protected endpoints | `True`            |\n| `AUTH_AUDIENCE`                 | Comma-separated accepted JWT audiences           | `AZURE_CLIENT_ID` |\n| `AUTH_SCOPE                   ` | Delegated scope accepted for helpdesk access     | `access_as_user`  |\n| `AUTH_JWKS_CACHE_TTL_SECONDS`   | Time to cache JWKS keys (reduce latency)         | `3600`            |\n| `AUTH_ROLE_HELPDESK`            | Comma-separated list of valid roles              | `helpdesk`        |\n| `AUTH_ROLE_HR`                  | Comma-separated list of valid roles              | `hr`              |\n\n### Feature Flags\n\n| Variable         | Description                                     | Default     |\n| ---------------- | ----------------------------------------------- | ----------- |\n| `SWAGGER_ENABLE` | Expose `/api/docs` and `/api/openapi.json`      | `False`     |\n| `LOG_LEVEL`      | Log level (`DEBUG`, `INFO`, `WARNING`, `ERROR`) | `INFO`      |\n| `LOGO_URL`       | URL of the logo displayed in the navigation bar | placeholder |\n\n---\n\n## Azure App Registrations\n\nTwo App Registrations are required: one for the **Backend API** (used by the FastAPI service to call the Verified ID API and validate inbound JWTs), and one for the **Frontend SPA** (used by the Angular application to authenticate users via MSAL).\n\n---\n\n### App 1 — Backend API App Registration\n\nThis registration allows the backend to:\n\n- Acquire tokens to call the Microsoft Entra Verified ID Request Service\n- Validate JWT access tokens sent by the Angular frontend\n- Expose application roles (`helpdesk`, `hr`) and a delegated scope (`access_as_user`)\n\n#### Step 1 — Create the registration\n\n1. Open the [Azure portal](https://portal.azure.com) and navigate to **Microsoft Entra ID → App registrations → New registration**\n2. Fill in the form:\n   - **Name**: `VerifID – Backend API` _(or any name you prefer)_\n   - **Supported account types**: _Accounts in this organizational directory only (Single tenant)_\n   - **Redirect URI**: leave empty (the backend does not use redirect flows)\n3. Click **Register**\n4. Note the **Application (client) ID** — this is your `AZURE_CLIENT_ID`\n5. Note the **Directory (tenant) ID** — this is your `AZURE_TENANT_ID`\n\n#### Step 2 — Create a client secret\n\n1. In the app registration, go to **Certificates \u0026 secrets → Client secrets → New client secret**\n2. Add a description (e.g. `verifid-backend`) and choose an expiry\n3. Click **Add** and immediately copy the **Value** — this is your `AZURE_CLIENT_SECRET`\n\n\u003e ⚠️ The secret value is only shown once. Store it securely in a vault or as a Docker secret.\n\n#### Step 3 — Expose an API (Application ID URI and scope)\n\n1. Go to **Expose an API**\n2. Click **Set** next to _Application ID URI_ — accept the default (`api://\u003cclient-id\u003e`) or use a custom URI\n3. Click **Add a scope**:\n   - **Scope name**: `access_as_user`\n   - **Who can consent**: _Admins and users_\n   - **Admin consent display name**: `Access VerifID as a user`\n   - **Admin consent description**: `Allows the application to access the VerifID helpdesk API on behalf of the signed-in user`\n   - **State**: Enabled\n4. Click **Add scope**\n\n#### Step 4 — Declare application roles\n\nApplication roles are used for server-to-server authorization (`helpdesk`, `hr`).\n\n1. Go to **App roles → Create app role**\n\n**Role 1 — Helpdesk**\n\n| Field                | Value                                               |\n| -------------------- | --------------------------------------------------- |\n| Display name         | `Helpdesk`                                          |\n| Allowed member types | `Users/Groups`                                      |\n| Value                | `helpdesk`                                          |\n| Description          | `Access to helpdesk identity verification features` |\n| State                | Enabled                                             |\n\n**Role 2 — HR**\n\n| Field                | Value                                       |\n| -------------------- | ------------------------------------------- |\n| Display name         | `HR`                                        |\n| Allowed member types | `Users/Groups`                              |\n| Value                | `hr`                                        |\n| Description          | `Access to HR credential issuance features` |\n| State                | Enabled                                     |\n\n#### Step 5 — Grant the Verified ID permission\n\nThe backend needs to call the Verified ID Request Service using its own identity (client credentials flow).\n\n1. Go to **API permissions → Add a permission → APIs my organization uses**\n2. Search for **Verifiable Credentials Service Request** (App ID: `3db474b9-6a0c-4840-96ac-1fceb342124f`)\n3. Select **Application permissions** → `VerifiableCredential.Create.All`\n4. Click **Add permissions**\n5. Click **Grant admin consent for \\\u003cyour tenant\\\u003e** — this is required because it is an application permission\n\n#### Step 6 — Collect the configuration values\n\n| `.env` variable       | Where to find it                              |\n| --------------------- | --------------------------------------------- |\n| `AZURE_TENANT_ID`     | Overview → Directory (tenant) ID              |\n| `AZURE_CLIENT_ID`     | Overview → Application (client) ID            |\n| `AZURE_CLIENT_SECRET` | Certificates \u0026 secrets → the value you copied |\n| `AUTH_AUDIENCE`       | `api://\u003cclient-id\u003e` or the Application ID URI |\n\n---\n\n### App 2 — Frontend SPA App Registration\n\nThis registration allows the Angular application to sign users in via MSAL and obtain access tokens that are forwarded to the FastAPI backend.\n\n#### Step 1 — Create the registration\n\n1. Go to **Microsoft Entra ID → App registrations → New registration**\n2. Fill in the form:\n   - **Name**: `VerifID – Frontend SPA`\n   - **Supported account types**: _Accounts in this organizational directory only (Single tenant)_\n   - **Redirect URI**: Select **Single-page application (SPA)** and enter `https://yourdomain.com` (add `http://localhost:4200` during development)\n3. Click **Register**\n4. Note the **Application (client) ID** — this is your `AUTH_CLIENT_ID`\n\n#### Step 2 — Configure authentication\n\n1. Go to **Authentication**\n2. Under **Single-page application**, verify the redirect URI you entered\n3. Add additional redirect URIs if needed (e.g. `http://localhost:4200` for local dev)\n4. Under **Implicit grant and hybrid flows**, make sure **both checkboxes are unchecked** — MSAL v3/v4 uses the Authorization Code flow with PKCE; implicit grant is not needed and should remain disabled\n5. Under **Front-channel logout URL**, you can optionally add your logout page URL\n6. Click **Save**\n\n#### Step 3 — Add API permissions\n\nThe frontend needs permission to call the backend API using the scope created in App 1.\n\n1. Go to **API permissions → Add a permission → My APIs**\n2. Select **VerifID – Backend API**\n3. Select **Delegated permissions** → `access_as_user`\n4. Click **Add permissions**\n5. Click **Grant admin consent for \\\u003cyour tenant\\\u003e** _(optional but recommended to avoid per-user consent prompts)_\n\n#### Step 4 — Assign users to roles\n\nRoles are assigned via **Enterprise Applications**, not App Registrations.\n\n1. Navigate to **Microsoft Entra ID → Enterprise Applications**\n2. Search for **VerifID – Backend API** _(the enterprise app is automatically created alongside the app registration)_\n3. Go to **Users and groups → Add user/group**\n4. Select the users or groups you want to assign and pick the role (`Helpdesk` or `HR`)\n5. Click **Assign**\n\n\u003e Role assignments are reflected in the `roles` claim of the access token. Users without an assigned role will receive a 403 on protected endpoints.\n\n#### Step 5 — Collect the configuration values\n\n| `.env` variable  | Where to find it                                               |\n| ---------------- | -------------------------------------------------------------- |\n| `AUTH_CLIENT_ID` | Overview → Application (client) ID of the **SPA** registration |\n\n---\n\n### Summary Table\n\n| Purpose                                    | App Registration         | Key values                                                |\n| ------------------------------------------ | ------------------------ | --------------------------------------------------------- |\n| Backend token acquisition \u0026 JWT validation | `VerifID – Backend API`  | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AUTH_AUDIENCE` |\n| Frontend user sign-in (MSAL)               | `VerifID – Frontend SPA` | `AUTH_CLIENT_ID`                                          |\n\n---\n\n## Roles \u0026 Permissions\n\n| Role / Scope          | Grants access to                                |\n| --------------------- | ----------------------------------------------- |\n| `helpdesk` (app role) | `/api/v1/verified-id/assist/{code}`             |\n| `hr` (app role)       | `/api/v1/verified-id/issue`                     |\n| _(no auth)_           | `/verify` page and `/api/v1/verified-id/verify` |\n\nAuthentication can be disabled entirely by setting `AUTH_ENABLED=False` — useful during initial setup and testing.\n\n---\n\n## Development\n\n### Prerequisites\n\n- Python 3.14+\n- Node.js 18+\n- Angular CLI 21\n\nA ready-to-use **VS Code Dev Container** is included (`.devcontainer/`). Open the repository in VS Code and select **Reopen in Container** to get a fully configured environment with Python, Node, Angular CLI, and all dependencies installed automatically.\n\n### Backend\n\n```bash\ncd backend\ncp .env.example .env   # fill in your Azure values\nuv sync\nuvicorn app.main:app --reload --host 0.0.0.0 --port 8000\n```\n\nAPI docs are available at `http://localhost:8000/api/docs` when `SWAGGER_ENABLE=True`.\n\n### Frontend\n\n```bash\ncd frontend\nnpm install\nng serve --host 0.0.0.0   # proxies /api/* to http://localhost:8000\n```\n\nThe Angular dev server starts at `http://localhost:4200`.\n\n### Build \u0026 Run (local Docker)\n\n```bash\ndocker compose up --build\n```\n\n---\n\n## CI / CD\n\nA GitHub Actions workflow can be added to build and publish the Docker image automatically on every push to `main` and on version tags. The recommended tag strategy is `latest`, `X.Y.Z`, and `sha-\u003ccommit\u003e`.\n\n---\n\n## Healthcheck\n\n`GET /api/health` returns:\n\n```json\n{ \"status\": \"healthy\", \"service\": \"VerifID API\" }\n```\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE) for details.\n\nAuthor: [@cyr-ius](https://github.com/cyr-ius)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcyr-ius%2Fverifid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcyr-ius%2Fverifid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcyr-ius%2Fverifid/lists"}