UNPKG

@unqtech/age-verification-mitid

Version:

Frontend SDK for age verification via UNQVerify using MitID

257 lines (198 loc) 8.18 kB
# @unqtech/age-verification-mitid Frontend SDK for age verification using UNQVerify (MitID-powered). 🔗 Official site: [aldersverificering.dk](https://www.aldersverificering.dk) --- ### Contents - [Installation](#installation) - [Quick start (npm)](#quick-start-npm) - [Outcome codes](#outcome-codes) - [`init(config)` options](#initconfig-options) - [Other functions](#other-functions) - [Backwards compatibility](#backwards-compatibility) - [CDN / No-bundler usage](#cdn--no-bundler-usage) - [WooCommerce integration](#woocommerce-integration) - [Security](#security) - [License](#license) --- ## Installation ```bash npm install @unqtech/age-verification-mitid ``` TypeScript users can also import the types directly: ```ts import type { UnqVerifyConfig, VerificationErrorCode, VerificationOutcome } from '@unqtech/age-verification-mitid' ``` --- ## Quick start (npm) ```ts import { init, startVerificationWithRedirect, isVerified } from '@unqtech/age-verification-mitid' init({ publicKey: 'pk_test_abc123', ageToVerify: 18, redirectUri: 'https://yourapp.com/verify-result', onVerified: (payload) => console.log('Verified!', payload), onDenied: (outcome) => alert('You do not meet the age requirement.'), onCancelled: (outcome) => console.info('Cancelled:', outcome.code), onError: (outcome) => console.error('Error:', outcome.code, outcome.message), }) if (!isVerified()) { startVerificationWithRedirect() // or: startVerificationWithPopup() } ``` On the page your `redirectUri` points to: ```ts import { handleRedirectResult } from '@unqtech/age-verification-mitid' await handleRedirectResult({ onVerified: (payload) => { /* redirect user back */ }, onDenied: (outcome) => { /* show denied message */ }, onError: (outcome) => console.error(outcome.code, outcome.message), targetOrigin: 'https://yourapp.com', // recommended in popup mode }) ``` --- ## Outcome codes Every non-success path provides a `VerificationOutcome` object: ```ts interface VerificationOutcome { code: VerificationErrorCode // stable, machine-readable message: string raw?: unknown } ``` | Code | Callback | When | |---|---|---| | `UNDER_AGE` | `onDenied` | MitID returned `verification_result: false`. Covers both genuine under-age and user opting out at the MitID screen MitID sends the same response for both. | | `USER_CANCELLED` | `onCancelled` | User cancelled inside the MitID flow | | `POPUP_CLOSED` | `onCancelled` | User closed the popup window manually | | `POPUP_TIMEOUT` | `onCancelled` | Popup open > 5 minutes without result | | `POPUP_BLOCKED` | `onError` | Browser blocked the popup | | `NETWORK_ERROR` | `onError` | API call failed | | `TOKEN_INVALID` | `onError` | JWT missing, expired, or invalid signature | | `UNTRUSTED_ORIGIN` | `onError` | postMessage received from an untrusted origin | | `UNKNOWN_ERROR` | `onError` | Unexpected error | --- ## `init(config)` options | Option | Type | Required | Description | |---|---|---|---| | `publicKey` | `string` | yes | Your `pk_test_...` or `pk_live_...` key | | `ageToVerify` | `number` | yes | Minimum age threshold | | `redirectUri` | `string` | yes | HTTPS URL the user returns to after MitID | | `onVerified` | `(payload) => void` | yes | Called on successful verification | | `onDenied` | `(outcome) => void` | no | Age requirement not met | | `onCancelled` | `(outcome) => void` | no | Popup closed or timed out | | `onError` | `(outcome) => void` | no | Technical/system error | | `onFailure` | `(error?) => void` | no | Legacy catch-all (always invoked alongside granular callbacks) | | `debug` | `boolean` | no | Verbose SDK logging (default `false`) | --- ## Other functions | Function | Description | |---|---| | `startVerificationWithRedirect()` | Full-page redirect flow | | `startVerificationWithPopup(popup?)` | Popup flow | | `handleRedirectResult(opts)` | Process result on the redirect page | | `isVerified()` | `true` if user has a valid, non-expired token | | `getVerifiedAge()` | Verified age as `number`, or `null` | | `resetVerification()` | Clears the session cookie | --- ## Backwards compatibility `onFailure` is always called alongside any granular callback, so existing `v0.3` integrations continue to work unchanged. ```ts // v0.3 still works onFailure: (err) => showError(err) // v0.4 use granular callbacks instead onDenied: (outcome) => showMessage('Come back when you are older'), onCancelled: (outcome) => hideModal(), onError: (outcome) => reportError(outcome.code, outcome.raw), ``` --- ## CDN / No-bundler usage Load the self-contained UMD build directly no npm or build step required. ```html <script src="https://unpkg.com/@unqtech/age-verification-mitid@latest/dist/index.umd.js"></script> ``` All functions are available under `window.UnqVerify` after the script loads. --- ## WooCommerce integration ### 1 — Enqueue the script (`functions.php`) ```php add_action( 'wp_enqueue_scripts', function () { if ( is_shop() || is_product() || is_product_category() || is_cart() || is_checkout() ) { wp_enqueue_script( 'unqverify-sdk', 'https://unpkg.com/@unqtech/age-verification-mitid@latest/dist/index.umd.js', [], null, true ); } } ); ``` ### 2 — Initialize and gate the page ```php add_action( 'wp_footer', function () { if ( ! ( is_shop() || is_product() || is_product_category() || is_cart() || is_checkout() ) ) { return; } ?> <script> (function () { var PUBLIC_KEY = 'pk_live_YOUR_KEY'; var REDIRECT_URI = '<?php echo esc_js( home_url( '/aldersverificering/' ) ); ?>'; if ( window.location.pathname.indexOf( '/aldersverificering' ) !== -1 ) { UnqVerify.init({ publicKey: PUBLIC_KEY, ageToVerify: 18, redirectUri: REDIRECT_URI, onVerified: function () { var returnTo = sessionStorage.getItem( 'unqverify_return' ) || '<?php echo esc_js( wc_get_page_permalink( "shop" ) ); ?>'; window.location.href = returnTo; }, onDenied: function () { alert( 'Du opfylder desværre ikke alderskravet.' ); }, onError: function () { alert( 'Aldersverificering mislykkedes. Prøv venligst igen.' ); } }); UnqVerify.handleRedirectResult({ onVerified: function () {}, onDenied: function ( outcome ) { console.warn( outcome.code ); }, onError: function ( outcome ) { console.error( outcome.code ); } }); return; } UnqVerify.init({ publicKey: PUBLIC_KEY, ageToVerify: 18, redirectUri: REDIRECT_URI, onVerified: function () {}, onError: function () {} }); if ( ! UnqVerify.isVerified() ) { sessionStorage.setItem( 'unqverify_return', window.location.href ); UnqVerify.startVerificationWithRedirect(); } })(); </script> <?php } ); ``` ### 3 — Create the verification result page 1. Go to **Pages Add New** in WordPress admin 2. Set the slug to `aldersverificering` (matching `REDIRECT_URI` above) 3. Leave the content empty the script handles everything 4. Register the URL as an **Allowed redirect URI** in your UNQVerify dashboard --- ## Security - All JWTs are RS256-verified against the issuer's JWKS endpoint - Unknown issuers are always rejected - `postMessage` events are validated against a strict origin allowlist - The `unqverify_token` cookie is set with `SameSite=Lax; Secure` - Cookie lifetime is the greater of the JWT `exp` claim or **1 hour**, ensuring the verification session is not lost too quickly even if the token has a short TTL JWKS endpoints: ``` https://test.api.aldersverificering.dk/well-known/openid-configuration/jwks (test) https://api.aldersverificering.dk/well-known/openid-configuration/jwks (live) ``` --- ## License MIT © UNQTech ApS