Drop-in widget · Tier B1
Sign in with EU Wallet — one script tag
Add EU Wallet sign-in to any web page in about 30 seconds. The widget renders a branded button, opens a QR modal on click, polls the CodeB verifier for the wallet’s response, and fires a codeb:wallet-signed-in DOM event on the host page. No backend integration is required on your side beyond verifying the returned assertion server-side.
Live demo
Click the button below. A modal will open with a scannable QR pointing at the CodeB verifier on this domain.
Nothing wires the button to your app until you handle the event — the demo just prints the payload below.
Waiting for a wallet response…
Integration snippet (copy-paste)
<!-- 1. Placeholder where the button should render -->
<div id="my-login" data-codeb-widget="signin"
data-label="Sign in with EU Wallet"></div>
<!-- 2. Load the widget from your CodeB verifier origin -->
<script src="https://phone.aloaha.com/signin-widget.min.js"
data-verifier="https://phone.aloaha.com"
data-mode="signin"
data-theme="auto"
async defer></script>
<!-- 3. Handle the callback and POST the assertion to your backend -->
<script>
window.addEventListener('codeb:wallet-signed-in', function(e) {
var assertion = e.detail.assertion;
var claims = e.detail.claims;
console.log('Verified claims:', claims);
// POST assertion to your server; verify it against the CodeB verifier
// JWKS at https://phone.aloaha.com/.well-known/openid-configuration.
});
</script>
Data attributes on the <script> tag
| Attribute | Default | Effect |
|---|---|---|
data-verifier | https://phone.aloaha.com | Origin serving oidc.ashx. Set to your own tenant domain. |
data-mode | signin | Currently signin only. age-verify lands with the dedicated backend endpoint in the next iteration. |
data-theme | auto | light, dark, or auto (follows the browser’s prefers-color-scheme). |
data-debug | false | Set to true to see widget lifecycle in the browser console. |
Data attributes on the placeholder <div>
| Attribute | Effect |
|---|---|
data-codeb-widget="signin" | Required. Marks the div for widget insertion. |
data-label | Override the button label (default: Sign in with EU Wallet). |
Events fired on window
codeb:wallet-signed-in
e.detail.claims holds the verified SD-JWT VC claims (given_name, family_name, age_over_*, whatever the wallet released). e.detail.assertion holds a signed CodeB assertion your server verifies against the verifier JWKS.codeb:wallet-declined
User pressed “deny” in the wallet. Nothing to verify server-side.
codeb:wallet-expired
The 5-minute presentation session timed out. Ask the user to try again.
codeb:wallet-error
Wallet or verifier returned an error.
e.detail.error holds the reason.Programmatic API
If you prefer not to use the auto-rendered button, call the API directly:
CodeBEuWallet.open({ mode: 'signin' }); // opens the modal
CodeBEuWallet.close(); // closes it
CodeBEuWallet.config(); // reads current config
CodeBEuWallet.version; // '2026-07-12-nadur'
Security & privacy
Origin isolation
The widget only talks to the
data-verifier origin. No third-party trackers, no cookies, no analytics.Cross-origin fetches use
credentials: 'omit'
Your visitor’s session cookies never leave your site.Modal cannot be spoofed by other origins
Rendered from the widget script only; no iframes, no cross-frame messaging.
Assertion verification is server-side
Never trust the browser’s
e.detail.claims alone. POST e.detail.assertion to your backend and verify against the CodeB verifier JWKS.
Legal footing. The widget makes no certification claim. See HAIP implementation notes for our honest position on OpenID Foundation conformance testing.
EU Wallet verifier overview · HAIP notes · Try full sign-in · Age verification