usermanual

Technical Documentation

itsme integration: how it works

How itsme eID verification is wired into Unidy and how the building blocks interlock.

What itsme is

itsmeยฎ is the Belgian government-backed eID (Belgian Mobile ID). It is a standards-compliant OpenID Connect provider that returns legally verified identity claims (KYC) - official name, birthdate, and Belgian national-register number - and is used by Pro League clubs to verify fans identity before enter the stadium.

Unidy's two OIDC roles

itsme touches both directions of Unidy's authentication:

Roboticket (ticketing)
      ^
      |  Unidy is the OIDC Provider (IdP): issues an ID token incl. verified / verified_at
      |
  [ UNIDY ]
      |
      |  Unidy is the OIDC Client (RP): receives itsme KYC claims
      v
itsme  (idp.prd.itsme.services)
  • Inbound (Unidy receives from itsme): Unidy is the relying party. itsme is configured as Unidy's single openid_connect login provider; the OmniAuth callback consumes the claims.
  • Outbound (Unidy sends to Roboticket): Unidy is the IdP. Roboticket reads the verification result from Unidy's ID token via configured OIDC claims.

The building blocks (and how they interlock)

  1. itsme = the openid_connect login provider. itsme uses Unidy's generic OIDC slot. Discovery: https://idp.prd.itsme.services/v2/.well-known/openid-configuration (use e2e for sandbox). Scopes must include openid and service:<your-code>, plus profile email address phone, and eid for the national number. The provider is marked as a KYC (identity-verifying) provider - that flag, not anything itsme-specific in code, is what makes a successful login set verification.
  1. Verification flag. A successful login or link with a KYC provider stamps user.verified_at. The verified flag is derived from verified_at (present and within the 1-year window) - it is never stored or hand-maintained as a custom attribute. Separately, the provider's claim mappings copy itsme profile claims (given_name to first name, family_name to last name, birthdate to date of birth, http://itsme.services/v2/claim/BENationalNumber to a custom attribute, and so on) onto the Unidy user.
  1. Deduplication. Each itsme identity (sub) is stored as a SocialLogin (provider, uid) with a unique index, so one itsme identity can belong to exactly one Unidy account.
  1. Post-login connect flow. A signed-in fan (for example one who registered manually) can verify without re-registering: GET /verify/connect starts itsme OAuth for the current user, links the identity, stamps verified_at, and returns them where they came from.
  1. No-email fans. itsme may not share an email. Those users get a synthetic <uuid>@kyc.invalid address so sign-up succeeds, then a hard gate requires them to add a real email (with a confirmation mail) before using Unidy or completing SSO.
  1. Yearly reverification. user.verified_at is the single source of truth. A daily job clears it after 1 year (Pro League requirement), and because verified is derived, the flag flips to false automatically. Both verified and verified_at are exposed to Roboticket so it can enforce the same window.
  1. Manual verification. Admins can tick a Verified checkbox on the user for box-office or under-16 cases; this stamps verified_at, so it expires on the same yearly cycle. There is no verified custom attribute to edit.
  1. Fan-facing. When a fan is not verified, the profile page shows a Verify with itsme prompt (during an OAuth connect that requires verification); once verified, the profile shows a verified badge with the date.

The two end-to-end flows (RSCL)

  • Flow 1 - register with itsme: the fan signs up via itsme, KYC data and verified status are shared with Roboticket, and the fan can buy.
  • Flow 2 - manual account: the fan registers without KYC, Roboticket sees "not verified" and blocks the sale, sending the fan back to Unidy. The fan clicks Verify with itsme on the profile page, runs itsme OAuth, verified_at is stamped and KYC is shared, and the fan returns to Roboticket and can buy.
ย 

No-email fans: the data flow

itsme does not always share an email, and any email it does share is unverified. Unidy handles this without blocking verification:

  1. itsme returns no email. Instead of failing, Unidy creates the account with a synthetic address <uuid>@kyc.invalid (the .invalid TLD can never receive mail). The account is confirmed, verified_at is stamped, and the itsme KYC claims are mapped as usual.
  1. The account is flagged as needing a real email, detectable by its @kyc.invalid domain.
  1. A hard gate collects a real email. On any Unidy web page, and on the OIDC authorize step for interactive logins, the fan is redirected to an "add your email" gate and cannot proceed until they enter a real one. Silent prompt=none SSO returns an OIDC error instead of showing the gate.
  1. Double opt-in. The entered email is stored as the pending (unconfirmed) email and a confirmation mail is sent; the gate is satisfied at this point, so the fan can continue while confirmation is pending.
  1. Confirmation. When the fan clicks the confirmation link, the real email replaces the synthetic one as their primary email.
Until a real email is confirmed, the email claim shared downstream (for example to Roboticket) is the synthetic @kyc.invalid placeholder.
The exact itsme issuer, scopes, claim names, and credential onboarding are covered in the setup guide (User Manual > Login & Signup).
Did this answer your question?
๐Ÿ˜ž
๐Ÿ˜
๐Ÿคฉ