CorePass
Start integrating

Quickstart: CorePass login in five minutes

Four steps from an empty project to a working passwordless login: register the client, drop in the QR snippet, handle the callback, and make your first verified-data call.

5 minute read · Updated 2026-09-05


This page is the shortest route from an empty project to a person signing in with CorePass, and it is deliberately narrow: it covers the login and the one call that makes the login useful, and it leaves everything else to the pages that follow. Sign-in and sign-up are the same act in CorePass, so there is no separate registration flow to build.

Before you start #

  • A CorePass Connector client, issued by CorePass. Ask for one at contact@corepass.net; the connector's own environment variables are set on the deployment side.
  • An application that can serve two HTML pages and receive a redirect on an HTTPS URL.
  • The app-auth library for your service, which is what exchanges an authorization code for a token. It ships an example.
  • The CorePass application on a phone, with an account created, for the person doing the signing in.

1. Register your application #

CorePass registers the client your application authenticates with, together with the redirect URI it comes back to. You receive a client id and a client secret; keep them in your own environment, alongside the gateway host for the environment you are integrating against.

.env
COREPASS_GATEWAY=https://auth-develop.corepassdev.eu
COREPASS_CLIENT_ID=<your client id>
COREPASS_CLIENT_SECRET=<your client secret>
COREPASS_REDIRECT_URI=https://your.example/callback
COREPASS_SCOPE="openid offline offline_access"

The scope string is the one the connector expects for a personal login. A client that also needs to act as a business adds one more scope — see business login.

2. Build the login page #

The login page is yours to design in whatever HTML and CSS you like. Two elements are fixed, because the connector fills them in: the QR code a person scans from a desktop, and the link a person taps on a phone. There are no passwords, email addresses or phone numbers anywhere in this page.

The QR code
<img alt="{{.link}}" src=" data:image/png;charset=utf-8;base64,{{.qrcode}}" />
The mobile link
<button>
  <a class="link" href="{{.link}}"> Login with CorePass </a>
</button>

The page also carries a hidden form and one script. The form holds the challenge, the identifier and the session for this login attempt; login.js posts it to the connector on an interval and redirects the browser as soon as the person has approved the sign-in in their application.

login.html
<form id="login-form" method="POST">
  <input type="hidden" name="challenge" value="{{.challenge}}" />
  <input type="hidden" name="identifier" value="{{.identifier}}" />
  <input type="hidden" name="session" value="{{.session}}" />
</form>

<script src="static/js/login.js"></script>

The file names matter. The login page must be called login.html and its sign-up twin register.html, and both must load login.js. The script's own handleClick helper is what sends a person between the two pages.

3. Handle the redirect back #

When the person approves the sign-in, the connector redirects them to the redirect URI you registered, with an authorization code in the query string.

Your redirect URI
GET /callback?code=<authorization code>&state=<your state> HTTP/1.1
Host: your.example

Exchange that code for a token using the app-auth library. The token names the person by their Core ID — their address in the Core ecosystem — and that address is the identifier you key your own user records on. There is nothing else to store: no credential of theirs is yours to hold.

4. Make your first call #

A Core ID on its own already replaces your login. The call below is what turns it into an onboarding decision: it asks the connector which of the fields you care about this person has verified in their CorePass application.

POST /api/v1/blockchain/verified
curl --request POST \
    --url https://auth-develop.corepassdev.eu/api/v1/blockchain/verified \
    --header 'Content-Type: application/json' \
    --data '{
        "user":"ab22b1671b4f7ccc0b16a87514adde84513b6348232e",
        "items": ["IDCARD_DOB", "DRIVER_LICENSE_DOCUMENT_NUMBER","EMAIL"]
    }'

A person who has verified some of what you asked for:

200 OK
{
  "verifiedItems": ["EMAIL"],
  "unVerifiedItems": ["IDCARD_DOB", "DRIVER_LICENSE_DOCUMENT_NUMBER"]
}

A person who has verified none of it:

200 OK
{
  "unVerifiedItems": ["IDCARD_DOB", "DRIVER_LICENSE_DOCUMENT_NUMBER", "EMAIL"]
}

If a field your process depends on comes back unverified, tell the person to complete that verification in their CorePass application: the data transfer cannot be started for a field they have not verified, and asking for one is refused.

What you have now #

  • A passwordless sign-in, with no credential of the person's stored on your side and no reset flow to build.
  • A stable identifier — the Core ID — that is the key to every other call on this API.
  • A reliable answer to “can this person prove what we need?”, before your onboarding flow asks them for anything.

The natural next step is the KYC data transfer, which is where those verified fields actually reach you, and it is the first point at which you need a callback endpoint of your own.

Troubleshooting #

Symptom Cause
The QR code never resolves and the page sits there. login.js is not loaded, or the hidden form is missing one of the challenge, identifier or session values it posts.
The sign-up link goes nowhere. The pages are not named login.html and register.html; the helper switches between the two by rewriting that word in the URL.
A field you need is never in verifiedItems. The person has not verified that document in their CorePass application, or you are asking for the wrong document's variant of the field — a date of birth exists separately for an ID card, a passport, a residence permit and a driver's licence.
A scope is refused rather than downgraded. Your client is not registered for it. Asking for a scope the client does not hold is refused outright.