ZKRINET Docs
Byggblock

BankID — Zkrinet-plugin

På Zkrinet: lägg till blocket under Byggblock i panelen — ett klick, din egen kod rörs inte och en ögonblicksbild tas först. Installationsstegen nedan gäller om du kör PocketBase själv, till exempel efter en export.

Logga in med svenskt BankID via en EU-baserad OIDC-mäklare: Idura (f.d. Criipto, Danmark) eller Signicat (Norge). Testat mot PocketBase 0.40.4.

Ärligt om vad som är vad

Själva inloggningen är PocketBase egen. PocketBase har en inbyggd OpenID Connect-leverantör (platserna oidc, oidc2 och oidc3 under OAuth2). Den sköter inloggningssidan, PKCE, kodutbytet, token och användardata. Pluginet bygger inte en egen inloggning. Det lägger till fyra saker:

  1. En kontroll som säger exakt vad som saknas och jämför dina inställningar mot mäklarens discovery-dokument.
  2. Förberedelse av users: BankID lämnar inte ut någon e-postadress, och utan ändringen kan PocketBase inte skapa kontot (MÄTT: 400 email: Cannot be blank). E-post blir valfri för BankID-konton men krävs fortfarande vid vanlig registrering.
  3. Namn: mäklarens name, eller förnamn + efternamn (given_name + family_name) om name saknas.
  4. Personnummer: sparas inte som standard och tas bort ur svaret till webbläsaren (se GDPR nedan). Om du vill kan du slå på en koppling via hash, så att kontot överlever ett byte av mäklare.

Installera

Kopiera pb_hooks/ och pb_migrations/ in i projektet och starta om. Sätt Application URL under Settings till din riktiga adress (https).

Kontrollen

GET /api/zk/bankid/kontroll                                              (superuser)
GET /api/zk/bankid/kontroll?discovery=https://…/.well-known/openid-configuration

Svarar med:

Utan ?discovery= hämtas <första issuer>/.well-known/openid-configuration, eller annars samma sökväg på Auth URL:ens adress. Hos Signicat ligger issuern under en sökväg, så ge då adressen från Signicats Dashboard (Well-Known URL).

Steg för steg: Idura

  1. Skapa ett konto hos Idura och en Application i Idura Dashboard. Du får en domän på formen ditt-namn.idura.broker (testdomän först, produktionsdomänen registreras separat).
  2. Lägg till återkopplingsadressen från kontrollen som callback URL. Slå på OAuth2 Code Flow och skapa en client secret. Kopiera Client ID (realm) och hemligheten.
  3. I PocketBase: Collections → users → ⚙ → OAuth2 → Add provider → OpenID Connect (platsen oidc).
    • Client ID + Client secret från steg 2. Display name: BankID.
    • Kör GET /api/zk/bankid/kontroll?discovery=https://ditt-namn.idura.broker/.well-known/openid-configuration och klistra in forslag: Auth URL (slutar med ?acr_values=urn:grn:authn:se:bankid), Token URL, User info URL.
  4. Kör kontrollen igen tills varningar är tom.
  5. Test-BankID: Idura hänvisar till BankID:s testportal (developers.bankid.com → test portal). BankID-appen kan bara vara i test- eller produktionsläge, så använd gärna en separat telefon. Du väljer själv namn och ett giltigt testpersonnummer.
  6. Produktion: enligt Idura kräver BankID-certifikatet ett EU-momsnummer, och Idura beställer det via Swedbank (8–15 arbetsdagar).

Andra BankID-varianter hos Idura: urn:grn:authn:se:bankid:same-device (samma enhet) och urn:grn:authn:se:bankid:qr (QR).

Steg för steg: Signicat

  1. Skapa ett sandbox-konto hos Signicat. Enligt Signicat kan Swedish BankID läggas till i sandbox utan avtal (eID Hub → ID Methods).
  2. Skapa en OIDC-klient, lägg till återkopplingsadressen som redirect URI och skapa en hemlighet.
  3. Scopes: PocketBase begär alltid openid email profile och det går inte att ändra. Tillåt de tre på klienten (kontrollen varnar om discovery inte listar dem).
  4. I PocketBase: OpenID Connect som ovan. Hämta adresserna med GET /api/zk/bankid/kontroll?discovery=<Well-Known URL från Signicats Dashboard>. Auth URL ska sluta med ?acr_values=idp:sbid.
  5. Test-BankID: samma testportal hos BankID som ovan.

Priser: se respektive leverantör. Vi har inte kunnat källhänvisa några priser.

Knappen i din app

const { record, meta } = await pb.collection("users").authWithOAuth2({ provider: "oidc" })

BankID-konton har ingen e-post (record.email === ""). Behöver appen mejla användaren måste du fråga efter adressen separat. Om kontot är kopplat till BankID ser användaren själv (MÄTT):

const kopplingar = await pb.collection("_externalAuths").getFullList({ filter: 'provider = "oidc"' })

Personnummer och GDPR

Standard: personnumret sparas ingenstans. Pluginet tar bort det ur svaret till webbläsaren, eftersom PocketBase annars skickar med hela mäklarsvaret (meta.rawUser), personnummer i klartext inräknat (MÄTT). Testet söker igenom alla databasfiler i pb_data efter personnumret, byte för byte. Det som sparas är mäklarens sub (i _externalAuths) och namnet.

sub är en pseudonym per mäklare: hos Idura är den enligt dokumentationen unik per användare och Idura-tenant. Det betyder: byter du mäklare (eller tenant) får varje användare ett nytt sub och därmed ett nytt, tomt konto. Vi skriver det rakt ut eftersom det är en inlåsning.

Valfritt: koppling via hash. Sätt ZK_BANKID_PNR_NYCKEL (minst 32 slumpade tecken) så sparas HMAC-SHA256(personnummer, nyckel) i det dolda fältet users.bankid_pnr_hmac. Loggar samma person in med ett nytt sub kopplas inloggningen till samma konto (testat: byte på samma plats och byte mellan platser). Konsekvenser, ärligt:

Mäklaren behandlar personuppgifter åt dig. Teckna personuppgiftsbiträdesavtal med den.

Säkerhet

Begränsningar

Det här har vi INTE kunnat mäta

Miljövariabler

VariabelStandardVad
ZK_BANKID_LEVERANTORERoidcVilka OIDC-platser som är BankID (t.ex. oidc,oidc2 under ett mäklarbyte).
ZK_BANKID_PNR_NYCKEL(av)Minst 32 tecken. Slår på koppling via personnummer-hash.

Testa

./bank.py bankid

19 tester mot en låtsas-mäklare på 127.0.0.1 (discovery, token, userinfo, JWKS). Inget når internet. Testerna täcker migreringen, e-postkravet (även via batch), kontrollens varningar, inloggning utan e-post, namn, personnumret (sökt byte för byte i pb_data och i svaret), mäklarbyte, att en annan OIDC-plats inte kan ta över ett konto, det dolda fältet och PocketBase egen id_token-kontroll. Säkerhetstesterna och varningarna är verifierade med mutanter: 14 av 14 brutna skydd fångades. ID-token-testet signerar med RS256 och kräver Python-paketet cryptography på testmaskinen. Pluginet självt har inga beroenden.