Logga in med Dazr Identity: utvecklardokumentation
Standard-OpenID Connect 1.0 med authorization code-flödet och PKCE. Ingen SDK behövs: varje certifierat OpenID Connect-bibliotek fungerar, och det gör vanlig kod också.
Människor kan redan använda sitt Google- eller Microsoft-konto i Dazr Identity, så din app behöver inga separata Google- och Microsoft-knappar bredvid: en knapp i stället för tre.
Discovery och endpoints
Allt beskrivs i discovery-dokumentet. Peka ditt bibliotek mot utfärdaren så hittar det resten.
| Vad | Adress |
|---|---|
| Utfärdare (issuer) | https://identity.dazr.eu |
| Discovery | https://identity.dazr.eu/.well-known/openid-configuration |
| Auktorisering | https://identity.dazr.eu/oauth/authorize |
| Token | https://identity.dazr.eu/oauth/token |
| Användaruppgifter | https://identity.dazr.eu/oauth/userinfo |
| Offentliga nycklar (JWKS) | https://identity.dazr.eu/oauth/jwks |
| Återkallelse (RFC 7009) | https://identity.dazr.eu/oauth/revoke |
| Introspektion (RFC 7662), bara webbserverappar | https://identity.dazr.eu/oauth/introspect |
| Logga ut (RP-initiated logout) | https://identity.dazr.eu/oauth/logout |
| Verifieringsrapporter, bara webbserverappar | https://identity.dazr.eu/oauth/verification-report |
Registrera en app
- Appar tillhör en organisation. Ägare och administratörer i organisationen registrerar dem under Utvecklare.
- Webbserverappar (konfidentiella klienter) får en klienthemlighet som visas en gång. Autentisera mot token-endpointen med HTTP Basic (
client_secret_basic) eller i formulärets body (client_secret_post). - Single-page- och mobilappar (offentliga klienter) får ingen hemlighet. De skickar
client_idoch använder PKCE. - Omdirigerings-URI:er måste matcha exakt. De måste vara
https://. Medan appen är i testläge fungerarhttp://localhostochhttp://127.0.0.1på vilken port som helst också. - En adress till integritetspolicyn, en support-e-postadress och ett ändamål på en rad krävs: människor ser dem på samtyckesskärmen.

Integrationsguider
Varje stack nedan använder sitt eget standardstöd för OpenID Connect. Du behöver tre värden från konsolen: klient-id:t, klienthemligheten (bara webbserverappar) och den omdirigerings-URI du registrerade. Resten kommer från discovery-dokumentet.
- Auth.js / NextAuth
- Next.js App Router
- WordPress
- Laravel
- Supabase
- Django
- Node.js (openid-client)
- Vilket OpenID Connect-bibliotek som helst
sub är parvist: detsamma för alla appar i din organisation, olika för alla andra organisationer. Det ändras aldrig för en person, medan en e-postadress kan ändras. Spara sub som kontonyckel och behandla email som kontaktuppgift.
Auth.js / NextAuth
Auth.js (NextAuth.js v5) tar ett anpassat OpenID Connect-providerobjekt. Registrera en webbserverapp, ange AUTH_SECRET, AUTH_DAZR_ID och AUTH_DAZR_SECRET och använd den här callback-URL:en som omdirigerings-URI: https://app.example.eu/api/auth/callback/dazr.
// auth.ts
import NextAuth from "next-auth"
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
{
id: "dazr",
name: "Dazr Identity",
type: "oidc",
issuer: "https://identity.dazr.eu",
clientId: process.env.AUTH_DAZR_ID,
clientSecret: process.env.AUTH_DAZR_SECRET,
authorization: { params: { scope: "openid profile email" } },
checks: ["pkce", "state", "nonce"],
client: { id_token_signed_response_alg: "ES256" },
},
],
})
NextAuth.js v4 använder samma idé med type: "oauth" och discovery-URL:en:
// pages/api/auth/[...nextauth].ts (NextAuth.js v4), in providers: [ ... ]
{
id: "dazr",
name: "Dazr Identity",
type: "oauth",
wellKnown: "https://identity.dazr.eu/.well-known/openid-configuration",
clientId: process.env.DAZR_CLIENT_ID,
clientSecret: process.env.DAZR_CLIENT_SECRET,
authorization: { params: { scope: "openid profile email" } },
idToken: true,
checks: ["pkce", "state"],
client: { id_token_signed_response_alg: "ES256" },
profile(profile) {
return { id: profile.sub, name: profile.name ?? null, email: profile.email }
},
}
Next.js App Router
Med filen auth.ts ovan lägger du till route-hanteraren och en inloggningsknapp som kör en server action.
// app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth"
export const { GET, POST } = handlers
// app/page.tsx
import { auth, signIn, signOut } from "@/auth"
export default async function Page() {
const session = await auth()
if (session?.user) {
return (
<form action={async () => { "use server"; await signOut() }}>
<p>Signed in as {session.user.email}</p>
<button type="submit">Sign out</button>
</form>
)
}
return (
<form action={async () => { "use server"; await signIn("dazr") }}>
<button type="submit" className="dazr-signin">Sign in with Dazr Identity</button>
</form>
)
}
Utforma knappen som visas under Knappen. I callbacks är Dazrs sub lika med account.providerAccountId.
WordPress
Använd ett generiskt OpenID Connect-klienttillägg, t.ex. OpenID Connect Generic Client. Registrera en webbserverapp och fyll i tilläggets inställningar med värdena nedan. Tillägget visar den omdirigerings-URI som ska registreras på sin inställningssida; som standard är den https://example.com/wp-admin/admin-ajax.php?action=openid-connect-authorize.
| Inställning | Värde |
|---|---|
| Klient-id | ditt klient-id |
| Klienthemlighet | din klienthemlighet |
| Scope | openid profile email |
| Inloggnings-endpoint (auktorisering) | https://identity.dazr.eu/oauth/authorize |
| Token-endpoint | https://identity.dazr.eu/oauth/token |
| Endpoint för användaruppgifter | https://identity.dazr.eu/oauth/userinfo |
| Endpoint för avslutning av session | https://identity.dazr.eu/oauth/logout |
| Identitetsnyckel | sub |
| PKCE | på (S256) |
Namnen på inställningarna skiljer sig lite mellan tillägg. Har ett tillägg inget PKCE-alternativ, välj ett annat: Dazr Identity avvisar inloggningar utan PKCE.
Laravel
Laravel Socialite har ingen inbyggd generisk OpenID Connect-drivrutin, så lägg till en liten anpassad drivrutin. Den skickar människor till Dazr med PKCE och läser användaren från endpointen för användaruppgifter. Socialite läser inte discovery-dokumentet, så endpoints är utskrivna. Registrera en webbserverapp med omdirigerings-URI:n https://app.example.eu/auth/dazr/callback.
<?php
// app/Socialite/DazrProvider.php
namespace App\Socialite;
use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\User;
class DazrProvider extends AbstractProvider
{
protected $scopes = ['openid', 'profile', 'email'];
protected $scopeSeparator = ' ';
protected $usesPKCE = true;
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase('https://identity.dazr.eu/oauth/authorize', $state);
}
protected function getTokenUrl()
{
return 'https://identity.dazr.eu/oauth/token';
}
protected function getUserByToken($token)
{
$response = $this->getHttpClient()->get('https://identity.dazr.eu/oauth/userinfo', [
'headers' => ['Authorization' => 'Bearer '.$token],
]);
return json_decode((string) $response->getBody(), true);
}
protected function mapUserToObject(array $user)
{
return (new User)->setRaw($user)->map([
'id' => $user['sub'],
'name' => $user['name'] ?? null,
'email' => $user['email'] ?? null,
]);
}
}
// config/services.php
'dazr' => [
'client_id' => env('DAZR_CLIENT_ID'),
'client_secret' => env('DAZR_CLIENT_SECRET'),
'redirect' => env('DAZR_REDIRECT_URI'),
],
// app/Providers/AppServiceProvider.php, in boot()
use Laravel\Socialite\Facades\Socialite;
use App\Socialite\DazrProvider;
Socialite::extend('dazr', function ($app) {
return Socialite::buildProvider(DazrProvider::class, config('services.dazr'));
});
// routes/web.php
Route::get('/auth/dazr', fn () => Socialite::driver('dazr')->redirect());
Route::get('/auth/dazr/callback', function () {
$dazr = Socialite::driver('dazr')->user();
$user = \App\Models\User::updateOrCreate(
['dazr_sub' => $dazr->getId()],
['name' => $dazr->getName() ?? $dazr->getEmail(), 'email' => $dazr->getEmail()],
);
Auth::login($user);
return redirect('/');
});
Supabase
Supabase Auth har ingen generisk OpenID Connect-provider som du kan peka mot vilken utfärdare som helst: dess inloggningsleverantörer och integrationer med tredjeparts-auth är fasta listor. Så du kan inte lägga till Dazr Identity i Supabase-instrumentpanelen i dag. Om Supabase lägger till generiskt stöd för OpenID Connect, använd värdena från checklistan nedan.
Alternativet: logga in människor med Dazr Identity på din egen server (med en av guiderna på den här sidan), spara Dazrs sub i din användartabell och prata med Supabase från den servern med service role-nyckeln, medan du kontrollerar åtkomst i din egen kod. Skicka aldrig service role-nyckeln till en webbläsare.
Django
Använd mozilla-django-oidc. Registrera en webbserverapp med omdirigerings-URI:n https://app.example.eu/oidc/callback/. Biblioteket läser inte discovery-dokumentet, så endpoints är utskrivna.
# settings.py
import os
INSTALLED_APPS += ["mozilla_django_oidc"] # after django.contrib.auth
AUTHENTICATION_BACKENDS = [
"mozilla_django_oidc.auth.OIDCAuthenticationBackend",
"django.contrib.auth.backends.ModelBackend",
]
OIDC_RP_CLIENT_ID = os.environ["DAZR_CLIENT_ID"]
OIDC_RP_CLIENT_SECRET = os.environ["DAZR_CLIENT_SECRET"]
OIDC_RP_SCOPES = "openid profile email"
OIDC_RP_SIGN_ALGO = "ES256"
OIDC_OP_JWKS_ENDPOINT = "https://identity.dazr.eu/oauth/jwks"
OIDC_OP_AUTHORIZATION_ENDPOINT = "https://identity.dazr.eu/oauth/authorize"
OIDC_OP_TOKEN_ENDPOINT = "https://identity.dazr.eu/oauth/token"
OIDC_OP_USER_ENDPOINT = "https://identity.dazr.eu/oauth/userinfo"
OIDC_USE_PKCE = True
OIDC_PKCE_CODE_CHALLENGE_METHOD = "S256"
LOGIN_REDIRECT_URL = "/"
LOGOUT_REDIRECT_URL = "/"
# urls.py
from django.urls import include, path
urlpatterns += [path("oidc/", include("mozilla_django_oidc.urls"))]
# template: start the sign-in
# <a href="{% url 'oidc_authentication_init' %}">Sign in with Dazr Identity</a>
Som standard matchar backenden användare efter e-post. För att använda sub som kontonyckel gör du en underklass av OIDCAuthenticationBackend och skriver över filter_users_by_claims och create_user. Använd en aktuell version: äldre versioner kan inte verifiera ES256-signaturer.
Node.js (openid-client)
openid-client (version 6) läser discovery-dokumentet och kontrollerar PKCE, state, nonce och ID-token åt dig.
import * as client from 'openid-client';
const config = await client.discovery(
new URL('https://identity.dazr.eu'),
process.env.DAZR_CLIENT_ID,
process.env.DAZR_CLIENT_SECRET, // public client: pass undefined here and client.None() as the 4th argument
);
const redirect_uri = 'https://app.example.eu/auth/dazr/callback';
// 1. Start: keep the three random values in the user's session.
export async function start(session) {
session.verifier = client.randomPKCECodeVerifier();
session.state = client.randomState();
session.nonce = client.randomNonce();
return client.buildAuthorizationUrl(config, {
redirect_uri,
scope: 'openid profile email',
code_challenge: await client.calculatePKCECodeChallenge(session.verifier),
code_challenge_method: 'S256',
state: session.state,
nonce: session.nonce,
});
}
// 2. Callback: pass the full callback URL (a URL object).
export async function callback(session, currentUrl) {
const tokens = await client.authorizationCodeGrant(config, currentUrl, {
pkceCodeVerifier: session.verifier,
expectedState: session.state,
expectedNonce: session.nonce,
});
const claims = tokens.claims(); // sub, email, name
return { sub: claims.sub, email: claims.email, name: claims.name };
}
Vilket OpenID Connect-bibliotek som helst
Finns din stack inte på listan fungerar vilken OpenID Connect-klient som helst. Kontrollera dessa inställningar:
- Utfärdare
https://identity.dazr.eu, discovery-URLhttps://identity.dazr.eu/.well-known/openid-configuration. - Response type
code(authorization code-flöde). Inget implicit eller hybridflöde. - PKCE krävs, med
code_challenge_method=S256. - Scopes:
openidplus bara det du behöver avprofile,email,address,organisationsochoffline_access. Din app måste vara registrerad för varje scope den ber om. - Omdirigerings-URI: exakt som den registrerats i konsolen, inklusive sökvägen och eventuell query string.
- Klientautentisering:
client_secret_basicellerclient_secret_postför webbserverappar,noneför single-page- och mobilappar. - Signatur på ID-token: ES256. Vissa bibliotek antar RS256: ställ in algoritmen på ES256.
- Använd
subsom kontonyckel. Den är parvis, per organisation. - Med
offline_accessmåste du spara den nya refresh-token efter varje förnyelse: de roterar.
Flödet
- Skapa en slumpmässig
code_verifier(43 till 128 tecken) och desscode_challenge= base64url(SHA-256(verifier)). Skapa en slumpmässigstateochnonce. Spara alla tre i användarens session. - Omdirigera till authorization-endpointen med
response_type=code,client_id,redirect_uri,scope(alltid inklusiveopenid),state,nonce,code_challengeochcode_challenge_method=S256. - Personen loggar in om det behövs och ser samtyckesskärmen med de faktiska uppgifterna. När personen tillåter det kommer hen tillbaka till din omdirigerings-URI med
code,stateochiss. Kontrollera attstatematchar och attissärhttps://identity.dazr.eu. - På din server gör du en POST till token-endpointen med
grant_type=authorization_code,code, sammaredirect_uriochcode_verifier. - Verifiera ID-token: ES256-signatur med en nyckel från JWKS (matcha
kid),iss,aud= ditt klient-id,expoch dinnonce. Användsubsom kontonyckel.

Parametern prompt accepterar none (svara direkt med login_required eller consent_required om personen skulle behöva agera), login (be personen logga in igen) och consent (visa samtyckesskärmen även när den har godkänts tidigare). max_age stöds. Ihågkommet samtycke: om personen har godkänt samma scopes tidigare går hen direkt tillbaka till din app. Ber du om mer senare visar samtyckesskärmen bara det nya.
Scopes och claims
Be bara om det du behöver. Inget utanför den här tabellen finns: inga kontakter, inga filer, inga lösenord.
| Scope | Claims |
|---|---|
openid (krävs) | sub: ett slumpmässigt id för personen, detsamma för alla appar i din organisation och olika för alla andra organisationer |
profile | name (om angivet) och locale |
email | email och email_verified (alltid true) |
address | address (formatted, street_address, locality, region, postal_code, country), bara om personen har sparat en |
organisations | organisations: de organisationer som personen markerar på samtyckesskärmen, var och en med id, name, display_name, website, country, register_number, vat, vat_verified (bara true när EU:s VIES-tjänst har bekräftat momsregistreringsnumret), verified, verification (se Verifierade organisationer) och role (owner, admin eller member) |
offline_access | inga claims; du får också en refresh-token |
Claims visas i ID-token för de scopes som personen godkände. Endpointen för användaruppgifter returnerar samma uppsättning med aktuella värden.
Verifierade organisationer
Dazr verifierar bara en organisation när officiella källor bevisar två saker: vem personen är och att personen företräder den här organisationen, med dess namn, registreringsnummer och momsregistreringsnummer. Typiskt undertecknar vd:n en kort försäkran med en kvalificerad elektronisk signatur (QES) och lägger till utdraget från företagsregistret som nämner hen; med ett utdrag förseglat av registret, som den italienska visuran eller ett nederländskt KvK-utdrag, sker det direkt, annars granskar Dazr det. En kvalificerad signatur ensam gör aldrig en organisation verifierad. Varje organisation i claimet organisations har sin aktuella verifiering:

| verification.status | Betydelse |
|---|---|
unverified | Inte verifierad, eller en verifiering misslyckades, gick ut eller återkallades (t.ex. efter att det juridiska namnet eller organisationsnumret ändrades). |
pending | Verifieringen pågår: företrädaren har ombetts att underteckna, utdraget från företagsregistret saknas fortfarande, eller Dazr granskar dokument. method anger vilken väg som påbörjades, t.ex. qes (företrädaren undertecknar försäkran), qseal, pec, letter, video eller documents. |
verified | Verifierad. method är qes_org (kvalificerad signatur, certifikatet nämner organisationen), extract_sealed (kvalificerad signatur eller granskat id plus ett utdrag förseglat av företagsregistret), qes_reviewed (kvalificerad signatur, utdrag kontrollerat av Dazr), qseal (organisationens kvalificerade elektroniska stämpel), documents, pec (en kod som skickats till organisationens PEC-adress, Italien), letter (en kod som skickats med posten till det registrerade sätet), video (ett videosamtal med Dazr) eller extract. authority anger vad som bevisade att personen företräder organisationen (se nedan), och verified_at är en Unix-tidpunkt. |
Bara när status är verified anger verification.authority (och authority i webhooks) hur kopplingen mellan personen och organisationen bevisades:
| verification.authority | Betydelse |
|---|---|
certificate | Undertecknarens kvalificerade certifikat eller organisationens kvalificerade stämpel nämner organisationen med dess registreringsnummer. Med bara ett momsregistreringsnummer i certifikatet bevisade ett registerutdrag registreringsnumret. |
register_extract | Ett utdrag förseglat av företagsregistret, högst 3 månader gammalt, nämner organisationen med dess registrerings- och momsregistreringsnummer och anger undertecknaren som vd eller juridisk företrädare. |
reviewed | Dazr kontrollerade ett utdrag som nämner undertecknaren eller, utan kvalificerad signatur, utdraget och ett id. |
pec | En kod som skickats till PEC-adressen på visuran förseglad av registret (Italien). |
letter | En kod som skickats med posten till det registrerade sätet, efter att Dazr hade kontrollerat uppgifterna mot registret. |
video | Ett videosamtal med Dazr: ett id och ett officiellt utdrag som nämner personen. |
Booleanen verified behålls av kompatibilitetsskäl och är lika med verification.status === 'verified'. Varje organisation har också ett id, samma som webhooks använder.
När status är pending eller verified är verification.report_url adressen till dess verifieringsrapport.
"organisations": [{
"id": "org_3k9x2m0q8w1v5t7a", "name": "Conti Logistica S.r.l.", "country": "IT",
"register_number": "REA MI1234567", "vat": "IT12345678903", "vat_verified": true,
"display_name": "Conti", "website": "https://conti.example",
"verified": false, "verification": { "status": "pending", "method": "qes" }, "role": "owner"
}]
role och medlemskap läses om vid varje förnyelse av token och varje begäran om användaruppgifter: efter en rolländring har nästa svar den nya rollen, och en organisation som personen har lämnat eller tagits bort från finns inte längre med. När en administratör för organisationen kopplar bort din app utelämnas organisationen från tidigare utfärdade tokens tills en medlem delar den med din app igen vid en ny inloggning. display_name och website är null när organisationen inte har angett dem; name är alltid det juridiska namnet.
Kräv en verifierad organisation
Ställ i konsolen in Kräv en verifierad organisation på Verifiering påbörjad eller Verifierad, eller be om det per förfrågan med acr_values=urn:dazr:org:verification-started eller acr_values=urn:dazr:org:verified (den striktaste av de två vinner). Din app måste också begära scopet organisations.

En person utan en kvalificerande organisation tas igenom det i samma inloggning: namnet, organisationen (med momsregistreringsnumret kontrollerat i VIES) och sedan verifieringen. Personen kan underteckna direkt, få försäkran skickad till sig själv via e-post eller ange någon annan som undertecknar. Därefter markerar personen organisationen på samtyckesskärmen (bara kvalificerande organisationer kan markeras) och återvänder till din omdirigerings-URI.
Måste någon annan fortfarande underteckna kommer personen tillbaka med status pending, även när du bad om Verifierad: du får en kod, claimet säger pending, och ID-tokens acr är urn:dazr:org:verification-started i stället för urn:dazr:org:verified. Styr alltid åtkomst efter verification.status, aldrig efter att inloggningen lyckades. Med prompt=none får du interaction_required när kravet inte är uppfyllt.
Ändringar av inställningen gäller från nästa inloggning. Människor som redan är inloggade loggas inte ut: svar på förnyelser, endpointen för användaruppgifter och webhooks har alltid aktuell status, så använd dem för att reagera för befintliga sessioner.
Webhooks
Lägg till en webhook-URL (https) i konsolen. Du ser signeringshemligheten en gång; du kan rotera den. Dazr skickar organisation.verification.updated när en organisation som någon av dina användare har delat med din app blir pending, verified, failed eller unverified. Appar som aldrig har fått en organisation via samtycke får aldrig höra om det.
POST /your/webhook
Content-Type: application/json
Dazr-Event: organisation.verification.updated
Dazr-Delivery: dlv_8Fq2…
Dazr-Signature: t=1791021600,v1=5e0c…
{ "id": "evt_…", "type": "organisation.verification.updated", "created": 1791021600,
"data": { "organisation": { "id": "org_3k9x2m0q8w1v5t7a", "name": "Conti Logistica S.r.l.", "country": "IT" },
"status": "verified", "method": "qes_org", "authority": "certificate", "verified_at": 1791021598,
"report_url": "https://identity.dazr.eu/oauth/verification-report?org=org_3k9x2m0q8w1v5t7a",
"subjects": ["Xo1c…"] } }
status är pending, verified, failed eller unverified. subjects är sub-värdena i din app för de personer som har delat den här organisationen med den. Kontrollera signaturen innan du litar på body:n:
import crypto from 'node:crypto';
// raw = the request body exactly as received (a string), header = the Dazr-Signature header
function verifyDazrSignature(raw, header, secret) {
const m = /^t=(\d+),v1=([a-f0-9]{64})$/.exec(header || '');
if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false; // reject old deliveries
const want = crypto.createHmac('sha256', secret).update(m[1] + '.' + raw).digest('hex');
return crypto.timingSafeEqual(Buffer.from(want), Buffer.from(m[2]));
}
Svara med vilken 2xx som helst inom 8 sekunder. Annars försöker Dazr igen efter ungefär 5 minuter, 30 minuter, 2, 6, 12 och 24 timmar och markerar sedan leveransen som misslyckad. Varje försök har samma Dazr-Delivery-id, så ignorera dubbletter. Konsolen visar de senaste leveranserna, kan skicka en igen och kan skicka en testhändelse (webhook.test). Polling av endpointen för användaruppgifter fungerar också.
Företagsverifiering (KYB)
Företagsverifiering är den högre tillitsnivån ovanpå organisationsverifiering. Den lägger till vem som äger och leder företaget: företagsregistret, en ID-kontroll med selfie för företrädaren och för varje verklig huvudman, ägarstrukturen samt screening för sanktioner och PEP. Organisationen betalar 25 € exkl. moms, en gång; avbryter den innan någon ID-handling har kontrollerats återbetalas hela beloppet.

- Företagsuppgifter. Den juridiska formen samt registreringsnummer och säte från organisationens juridiska uppgifter, bekräftade av den som startar verifieringen.
- Betalning. 25 € exkl. moms via Mollie; fakturan finns på organisationens sida.
- ID-handling och selfie. Företrädaren fotograferar ett pass, ID-kort eller uppehållstillstånd (fram- och baksida vid behov) och tar två selfies, den andra med en slumpmässig vridning eller lutning av huvudet. En AI-modell läser handlingen; Dazr kontrollerar den maskinläsbara zonen (kontrollsiffror enligt ICAO 9303), datumen och namnet; en tjänst för ansiktsjämförelse jämför selfien med fotot i handlingen. En QR-kod flyttar fotograferingen från en dator till en telefon.
- Kontroll i företagsregistret. Namn, status och ledning från det officiella registret där det finns online (Norge, Danmark, Finland, Frankrike, Nederländerna, Polen, Tjeckien och Storbritannien, inklusive dess register över personer med betydande kontroll), annars från ett officiellt utdrag som är högst 3 månader gammalt.
- Vem äger företaget? Varje person med 25 % eller mer av andelarna eller rösterna, direkt eller via andra bolag (med kedjan), eller med kontroll på annat sätt. Uppfyller ingen detta räknas ledningen som verkliga huvudmän.
- Ägarna verifierar. Varje ägare får en länk med e-post, bekräftar den med en engångskod och gör samma ID-kontroll. Påminnelser skickas efter 2 och 7 dagar; länkar går ut efter 14 dagar.
- Sanktions- och PEP-kontroller. Företaget och varje person mot EU:s, FN:s och OFAC:s sanktionslistor och för politiskt exponerade personer.
- Beslut. Dokumenterade riskregler godkänner ärenden utan anmärkning. Allt annat går till en granskare på Dazr, som kan godkänna, avslå med en motivering, be organisationen om mer information eller köra en kontroll igen. Högriskärenden kräver två granskare. Inget ärende avslås automatiskt.
Godkända organisationer screenas mot sanktionslistorna igen varje dag och för PEP-status regelbundet. En ny träff skickar tillbaka verifieringen till granskning, och din app får veta det.
Claimet kyb
Varje organisation i claimet organisations innehåller kyb, och verification.assurance_level sammanfattar båda nivåerna: none, basic (organisationen verifierad) eller kyb (företagsverifiering godkänd).
| kyb.status | Betydelse |
|---|---|
none | Ingen företagsverifiering, eller så avbröts den senaste eller gick ut. |
in_progress | Påbörjad: organisationen går igenom stegen, eller ägare behöver fortfarande få sin ID-handling kontrollerad. |
in_review | Inskickad och under granskning hos Dazr, eller tillbaka i granskning efter en ny träff i screeningen. |
approved | Godkänd. Först då innehåller claimet verified_claims. |
rejected | Inte godkänd. Organisationen kan starta en ny. |
Efter godkännande följer verified_claims formatet OpenID Connect for Identity Assurance:
"kyb": {
"status": "approved",
"report_url": "https://identity.dazr.eu/oauth/verification-report?org=org_3k9x2m0q8w1v5t7a",
"verified_claims": {
"verification": {
"trust_framework": "dazr_kyb", "assurance_level": "kyb", "time": "2026-10-06T09:14:03.000Z",
"verification_process": "kyb_7Tq2…",
"evidence": [
{ "type": "electronic_record", "check_details": [{ "check_method": "data", "organization": "no-brreg" }] },
{ "type": "document", "check_details": [{ "check_method": "vpip" }, { "check_method": "pvr" }],
"note": "ID document and selfie with liveness of the representative and each beneficial owner" }
]
},
"claims": {
"legal_name": "Fjordline Logistikk AS", "country": "NO", "registration_number": "912345678",
"beneficial_owners_verified": 2,
"screening": { "result": "no_match_found", "pep_checked": true, "last_screened_at": "2026-10-06T03:23:00.000Z" },
"risk_level": "low"
}
}
}
Claimet innehåller aldrig namn, födelsedatum eller dokumentuppgifter om ägarna. De finns i revisionsrapporten, som din app kan hämta för organisationer som delats med den.
Kräva företagsverifiering
Ställ i konsolen in Kräv en verifierad organisation på Företagsverifiering (KYB), eller be om det per begäran med acr_values=urn:dazr:org:kyb. Den som inte har det än startar det i samma inloggning och kan fortsätta till din app direkt efteråt; de återstående stegen, som ägarnas ID-kontroller, sker senare. ID-tokenets acr är urn:dazr:org:kyb först när en organisation är godkänd, så kontrollera alltid kyb.status === 'approved' innan du låser upp något som kräver det.
Webhooks för företagsverifiering
Samma händelse organisation.verification.updated skickas när statusen för företagsverifieringen ändras, även efter en ny screening. Dess data innehåller dessutom:
"kyb": { "status": "approved", "approved_at": 1791021598, "risk_level": "low" },
"assurance_level": "kyb"
Företagsverifiering på egen hand
En organisation kan också starta företagsverifiering från sin sida i Dazr Identity, utan att någon app ber om det. Resultatet är detsamma: en verifiering per organisation, som varje app som organisationen delas med kan lita på. Bilder av ID-handlingar och selfies raderas 30 dagar efter beslutet; resultaten och rapporten sparas i 5 år efter att verifieringen har upphört, som penningtvättsreglerna kräver.
Verifieringsrapporter för revisioner
För varje organisation som har delats med din app kan du hämta en rapport om hur och när Dazr verifierade den, för din revisionsakt. Den finns medan organisationen är verifierad och medan verifieringen pågår, och visar då det som har gjorts hittills.
- Organisationen: namn, land, registreringsnummer, momsregistreringsnummer och registrerat säte.
- Verifieringen: status, metod, behörighet och när den begärdes, undertecknades och verifierades.
- Underlaget: för en kvalificerad signatur eller en kvalificerad stämpel undertecknarens namn som på certifikatet, certifikatets utfärdare, serienummer, giltighet och SHA-256-fingeravtryck, dess kvalificerade status (QC-uttalanden, tillhandahållare av betrodda tjänster och tjänst från EU:s förtroendelista, med listans löpnummer och utfärdandedatum), signeringstidpunkten och kontrollen av återkallelse. För ett registerförseglat utdrag vem som förseglade det, när och vad som matchade: namn, registreringsnummer, momsregistreringsnummer, vd. VIES-resultatet. För en PEC-kod, ett brev eller ett videosamtal datumen och de kontroller som en granskare på Dazr markerade, visade som "Granskare på Dazr" med ett internt id.
- För dina akter: SHA-256-fingeravtrycket av varje underlagsfil, ett dokument-id, när rapporten genererades och en kort förklaring av varje metod och av vad behörighet betyder.
En rapport innehåller aldrig bilder eller nummer från identitetshandlingar, engångskoder, PEC-adressen, e-postadresser eller andra adresser än det registrerade sätet.
Hämta en rapport
Autentisera med ditt klient-id och din klienthemlighet, som vid token-endpointen: HTTP Basic (client_secret_basic) eller formulärets body i en POST (client_secret_post). Lägg aldrig hemligheten i URL:en. Använd organisationens id från claims eller webhooks, eller helt enkelt den verification.report_url som de innehåller.
curl -u "$DAZR_CLIENT_ID:$DAZR_CLIENT_SECRET" -o report.pdf \
"https://identity.dazr.eu/oauth/verification-report?org=org_3k9x2m0q8w1v5t7a&format=pdf&lang=en"
| Parameter | Betydelse |
|---|---|
org | Organisationens id. |
format | pdf (standard) eller jws, samma fakta som signerad JSON. |
lang | PDF:ens språk: en (standard), nl, it, de, fr, es eller pl. |
doc | I stället för rapporten: declaration, vd:ns signerade försäkran (bara kvalificerad signatur eller stämpel), eller extract, utdraget från företagsregistret. |
Bara organisationer som minst en av dina användare har delat med din app via samtycke kan hämtas. Varje annan organisation svarar 404, precis som en som inte finns eller inte har någon verifiering; en felaktig klienthemlighet svarar 401. Appar utan klienthemlighet kan inte hämta rapporter. Nedladdningar är hastighetsbegränsade, och varje nedladdning visas i organisationens aktivitet för dess administratörer med din apps namn. I konsolen visar din apps sida de anslutna organisationerna med samma nedladdningar.
Verifiera den signerade JSON:en
Med format=jws får du en kompakt JWS (ES256, huvud typ dazr-verification-report+jwt), signerad med samma nycklar som ID-tokens. Dess claims är iss, iat, jti (dokument-id:t), sub (organisationens id), aud (ditt klient-id) och report, fakta. PDF:en innehåller samma JWS på sista sidan och i sina metadata (DazrVerificationReport), så att en PDF också kan kontrolleras offline.
import { createRemoteJWKSet, jwtVerify } from 'jose';
const jwks = createRemoteJWKSet(new URL('https://identity.dazr.eu/oauth/jwks'));
// jws = the response body of format=jws, or the text from the PDF metadata
const { payload } = await jwtVerify(jws, jwks, {
issuer: 'https://identity.dazr.eu',
audience: process.env.DAZR_CLIENT_ID,
typ: 'dazr-verification-report+jwt',
});
console.log(payload.report.verification.status, payload.report.verification.authority);
Låt en revisor kontrollera signaturen
För en kvalificerad signatur eller en kvalificerad stämpel returnerar doc=declaration den signerade försäkran exakt som den laddades upp: en signerad PDF (PAdES) eller en .p7m-fil (CAdES). En revisor kan validera den oberoende med Europeiska kommissionens DSS-demovaliderare: ladda upp filen, behåll standardpolicyn för validering och kör den. Resultatet visar om signaturen är kvalificerad (QESig, eller QESeal för en stämpel), vem som undertecknade och tillhandahållaren av betrodda tjänster från EU:s förtroendelista. doc=extract returnerar utdraget från företagsregistret; ett registerförseglat utdrag kan valideras på samma sätt.
Rapporten är underlag för din revisionsakt. Reglerade företag ansvarar fortfarande för sina egna rutiner för kundkännedom.
Dazr sparar den signerade försäkran, utdraget och rapportdata medan organisationen är verifierad och i 5 år efter att dess verifiering upphör eller organisationen raderas. Spara egna kopior så länge dina regler kräver det.
Tokens och livslängder
| Token | Livslängd och regler |
|---|---|
| Auktoriseringskod | 60 sekunder, engångsanvändning, bunden till din klient, omdirigerings-URI och PKCE-challenge. Används en kod två gånger återkallas de tokens den utfärdade. |
| Access token | 10 minuter. En signerad JWT (ES256, typ at+jwt) med aud = ditt klient-id. Skicka den som Authorization: Bearer. |
| ID-token | 10 minuter. ES256, med iss, sub, aud, exp, iat, auth_time, nonce och amr, där det är känt. |
| Refresh token | Bara med offline_access. Roterar vid varje användning: spara alltid den nya. Skickas en gammal refresh token igen återkallas hela inloggningen. Går ut efter 30 dagar utan användning och senast efter 180 dagar. |
Signeringsnycklar roterar. Välj alltid nyckeln efter kid från JWKS och uppdatera JWKS när du ser ett okänt kid.
Fel
Så länge ditt klient-id och din omdirigerings-URI är giltiga kommer fel tillbaka till din omdirigerings-URI som error, error_description, state och iss: t.ex. invalid_request (som saknad eller plain PKCE), invalid_scope, unsupported_response_type, access_denied (personen avbröt, eller appen är i testläge och personen är inte medlem), login_required, consent_required och interaction_required (med prompt=none, när en krävd verifierad organisation saknas). Med en okänd klient eller en oregistrerad omdirigerings-URI visar Dazr en felsida och omdirigerar aldrig. Token-endpointen svarar med JSON-fel som invalid_client, invalid_grant och unsupported_grant_type.
Logga ut
För att logga ut en person skickar du hen till utloggnings-endpointen med id_token_hint (eller client_id), en valfri post_logout_redirect_uri som är registrerad i din apps inställningar och state. Dazr frågar om personen också vill logga ut från Dazr Identity på den enheten och skickar sedan tillbaka hen. Återkalla refresh tokens som du inte längre behöver vid revocation-endpointen.
Test och lansering
En ny app är i testläge: bara medlemmar i din organisation kan logga in, och det står på samtyckesskärmen. För att gå live måste du få din organisation verifierad i Dazr Identity, lägga till en https://-omdirigerings-URI och begära en live-granskning i konsolen. Ändring av namn, ändamål, integritetspolicy eller data för en live-app kräver en ny granskning.
Överför en app till en annan organisation
En app kan flyttas till en annan organisation som är registrerad hos Dazr, t.ex. efter en försäljning eller en omorganisation. En ägare eller administratör startar överföringen under Överför app i appens inställningar, i Dazr Identity eller i Sign-portalen. En ägare eller administratör för den andra organisationen godtar eller avvisar den inom 14 dagar. Fram till dess kan avsändaren avbryta, och inget ändras.
- Vem som kan ta emot den. Bara en organisation som är registrerad hos Dazr, angiven med sitt organisations-id. Dess ägare och administratörer hittar id:t i dess juridiska uppgifter i Dazr Identity. En live-app, en app under granskning, en app som kräver en verifierad organisation och en app med Dazr Sign API aktiverat kan bara flyttas till en verifierad organisation. Det kontrolleras igen när överföringen godtas.
- En färsk inloggning. Att starta och godta en överföring kräver en inloggning inom de senaste 10 minuterna.
- Vad som flyttas. Klient-id:t, inställningarna, logotypen, omdirigerings-URI:erna, de aktiverade API:erna och webhook-URL:erna. Den administratör som godtar godtar också utvecklarvillkoren för den nya organisationen.
- Klienthemligheten. En webbserverapp får en ny klienthemlighet som visas en gång för den administratör som godtar. Den tidigare hemligheten fortsätter att fungera vid token-, revocation- och introspection-endpointerna under den övergångsperiod som valdes när överföringen startade: ingen, 24 timmar (standard) eller 7 dagar. Verifieringsrapporter kräver den nya hemligheten.
- Webhooks. URL:erna stannar. Deras signeringshemligheter, för Dazr Identity och för Dazr Sign, förnyas och visas en gång för den administratör som godtar. Leveranser från före överföringen skickas inte igen.
- Personer och deras
sub. Varje person behåller sammasubi appen, så att kontona i din app fortsätter att fungera. Den skiljer sig från personenssubi den nya organisationens andra appar. Människor godkänner appen igen vid nästa inloggning, eftersom samtyckesskärmen nu nämner den nya organisationen. Tokens som utfärdats före överföringen slutar fungera. - Vad som stannar hos den tidigare ägaren. Antal inloggningar och samtycken och webhook-leveranser från före överföringen. Dokument som skapats via Dazr Sign API stannar hos de personer som äger dem, och appens nya ägare kan inte se dem.
Knappen
Använd formuleringen "Logga in med Dazr Identity" och Dazr-logotypen som nedan. Du får ändra storleken, inte logotypen, färgerna eller formuleringen. Länka den till din egen route som startar flödet.
<a href="/auth/dazr" style="display:inline-flex;align-items:center;gap:10px;height:44px;padding:0 18px;border-radius:22px;background:#18203a;color:#fff;font: 600 15px/1 'Dazr', system-ui, sans-serif;text-decoration:none">
<svg width="20" height="20" viewBox="0 0 100 100" aria-hidden="true"><path d="M50 4 89 16v31c0 25.5-16.8 42.5-39 50C27.8 89.5 11 72.5 11 47V16z" fill="#fff"/><path d="M50 15.5 79 24.5v22.8c0 19.5-12.4 32.6-29 38.7C33.4 79.9 21 66.8 21 47.3V24.5z" fill="#18203a"/><path d="M50 24 71 30.6v16.9c0 14.5-9 24.4-21 29.2-12-4.8-21-14.7-21-29.2V30.6z" fill="#fff"/></svg>
Sign in with Dazr Identity
</a>
Dazr-typsnittet. Knappen använder Dazr-typsnittet, som är fritt att använda under SIL Open Font License. Där Dazr inte är inläst används systemtypsnittet i stället. Ladda ned Dazr-typsnittet (ZIP med TTF- och WOFF2-filer) för att lagra det på din egen webbplats:
/* woff2 files from the ZIP, copied to /fonts/ on your site */
@font-face { font-family: 'Dazr'; font-weight: 400; font-display: swap;
src: url('/fonts/dazr-regular-latin.woff2') format('woff2'); }
@font-face { font-family: 'Dazr'; font-weight: 700; font-display: swap;
src: url('/fonts/dazr-bold-latin.woff2') format('woff2'); }
.dazr-signin { font: 600 15px/1 'Dazr', system-ui, sans-serif; }
Ett minimalt Node.js-exempel
Node 18 eller senare, inga beroenden. En webbserverapp med klienthemlighet; för en offentlig klient tar du bort Authorization-huvudet och skickar client_id i body:n.
import crypto from 'node:crypto';
const issuer = 'https://identity.dazr.eu';
const clientId = process.env.DAZR_CLIENT_ID;
const clientSecret = process.env.DAZR_CLIENT_SECRET;
const redirectUri = 'https://app.example.eu/auth/dazr/callback';
const b64url = (buf) => Buffer.from(buf).toString('base64url');
// 1. Start: keep verifier, state and nonce in the user's session.
export function start(session) {
session.verifier = b64url(crypto.randomBytes(32));
session.state = b64url(crypto.randomBytes(16));
session.nonce = b64url(crypto.randomBytes(16));
const challenge = b64url(crypto.createHash('sha256').update(session.verifier).digest());
return issuer + '/oauth/authorize?' + new URLSearchParams({
response_type: 'code', client_id: clientId, redirect_uri: redirectUri,
scope: 'openid profile email', state: session.state, nonce: session.nonce,
code_challenge: challenge, code_challenge_method: 'S256',
});
}
// 2. Callback: check state, exchange the code, verify the ID token.
export async function callback(session, query) {
if (query.error) throw new Error('sign-in failed: ' + query.error);
if (query.state !== session.state || query.iss !== issuer) throw new Error('state or issuer mismatch');
const res = await fetch(issuer + '/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: 'Basic ' + Buffer.from(clientId + ':' + clientSecret).toString('base64'),
},
body: new URLSearchParams({ grant_type: 'authorization_code', code: query.code, redirect_uri: redirectUri, code_verifier: session.verifier }),
});
const tokens = await res.json();
if (!res.ok) throw new Error(tokens.error);
const claims = await verifyIdToken(tokens.id_token, session.nonce);
return { sub: claims.sub, email: claims.email, name: claims.name, tokens };
}
async function verifyIdToken(idToken, nonce) {
const [h, p, s] = idToken.split('.');
const header = JSON.parse(Buffer.from(h, 'base64url'));
const { keys } = await (await fetch(issuer + '/oauth/jwks')).json();
const jwk = keys.find((k) => k.kid === header.kid);
if (!jwk || header.alg !== 'ES256') throw new Error('unknown signing key');
const ok = crypto.verify('sha256', Buffer.from(h + '.' + p),
{ key: crypto.createPublicKey({ key: jwk, format: 'jwk' }), dsaEncoding: 'ieee-p1363' }, Buffer.from(s, 'base64url'));
const c = JSON.parse(Buffer.from(p, 'base64url'));
const now = Math.floor(Date.now() / 1000);
if (!ok || c.iss !== issuer || c.aud !== clientId || c.exp < now - 30 || c.nonce !== nonce) throw new Error('invalid ID token');
return c;
}
Gränser
Authorization- och token-endpointerna är hastighetsbegränsade. Får du HTTP 429, vänta och försök igen; försök inte igen i en tät loop.
Dina skyldigheter
Din organisation är självständigt personuppgiftsansvarig för de uppgifter den får. Utvecklarvillkoren för Dazr Identity fastställer vad du får göra med dem, hur du håller dem säkra och hur du rapporterar incidenter. Frågor: hello@dazr.eu.