Adgangskontrol i sundhedssektoren – Beskyttelse af patientdata og kritiske områder

Digital adgangskontrol for hospitaler, klinikker og sundhedsfaciliteter. Compliance med autorisationsloven, GDPR og NIS2-krav.
5 min
Adgangskontrol i sundhedssektoren – Beskyttelse af patientdata og kritiske områder

Sundhedssektoren har kritiske sikkerhedsbehov: Beskyttelse af patientdata, medicin, og sikring af at kun autoriseret personale har adgang til følsomme områder.


Særlige krav i sundhedssektoren

⚕️ Autorisationsloven

Kun autoriseret sundhedspersonale må behandle patienter og håndtere medicin

GDPR-artikel 32

Særlige krav til beskyttelse af følsomme helbredsdata

NIS2-omfattet

Hospitaler og sundhedsmyndigheder er critical entities

Nødadgang

Beredskabsplaner skal sikre adgang i nødsituationer


Zoner og adgangsniveauer

Niveau 1: Offentlige områder
├─ Reception, venteværelser, cafeteria
├─ Adgang: Alle
└─ Logging: Minimal

Niveau 2: Patientområder
├─ Stuer, ambulatorier, undersøgelsesrum
├─ Adgang: Autoriseret sundhedspersonale + patienter
└─ Logging: Hvem, hvornår, formål

Niveau 3: Behandlingsområder
├─ Operationsstuer, intensive, dialyse
├─ Adgang: Specifik-certificeret personale
└─ Logging: Audit trail

Niveau 4: Medicindepot
├─ Opbevaring af receptpligtig medicin, euforiserende stoffer
├─ Adgang: Farmaceuter + autoriserede læger
├─ Dual-control: To personer krævet for euforiserende
└─ Logging: Video + digital sporbarhed

Niveau 5: IT & data
├─ Serverrum, arkiver med patientjournaler
├─ Adgang: IT-personale + ledelse
├─ Multi-faktor + tidsrestriktioner
└─ Logging: Integration med SIEM

Autorisation-validering

Autorisationstjekket (trin 1–3) kører i jeres eget system. Først når det er godkendt, udstedes nøglen gennem SnapKeys Public API med en API-nøgle, der har scopes people:write og keys:write:

# Validate healthcare professional authorization, then issue a key via the SnapKey Public API
import requests

SNAPKEY = "https://api.snapkey.dk/public/v1"
HEADERS = {"Authorization": "Bearer sk_live_..."}  # scopes: people:write, keys:write

def grant_medical_area_access(employee, area):
    # 1. Check if employee is healthcare professional (your own system)
    if not employee.is_healthcare_professional:
        raise Unauthorized("Only healthcare professionals allowed")

    # 2. Verify authorization with Styrelsen for Patientsikkerhed (your own integration)
    authorization = verify_authorization(cpr=employee.cpr, profession=employee.profession)
    if not authorization.is_active:
        raise Unauthorized("Authorization expired or revoked")

    # 3. Check specific area requirements (your own rules)
    if area.requires_specialization and employee.specialization not in area.allowed_specializations:
        raise Unauthorized(f"Specialization {employee.specialization} not authorized for {area.name}")

    # 4. Create the person in SnapKey – idempotent on phone and e-mail
    person = requests.post(f"{SNAPKEY}/people", headers=HEADERS, json={
        "name": employee.full_name,        # first and last name
        "email": employee.email,
        "phone": employee.phone,           # international format, e.g. +4520123456
        "title": employee.profession,
    })
    person.raise_for_status()

    # 5. Issue a key to the area's security group, valid while the authorization is
    invitation = requests.post(f"{SNAPKEY}/keys", headers=HEADERS, json={
        "person_id": person.json()["id"],
        "security_groups": [area.security_group],   # code from GET /security_groups
        "name": area.name[:50],
        "expires_at": authorization.valid_until.isoformat(),
        "channel": "sms",
    })
    invitation.raise_for_status()

    # 202 Accepted: an invitation, not a key. The key appears in GET /keys
    # (and fires the key.activated webhook) once the person activates the setup link.
    return invitation.json()["invitation_id"]

Medicindepot – Dual control

SnapKey har ingen tomandsgodkendelse, der kræver to personer, før en dør åbner. Dual control ved euforiserende stoffer sikres derfor i jeres procedure, for eksempel sådan:

1. Medicindepotet er markeret som kritisk lås
   └─ Sikkerhed får en alarm, når låsen bruges

2. Kun farmaceuter og autoriserede læger har nøgle

3. To personer er til stede efter jeres procedure

4. Åbningen logges med person og tidspunkt,
   når låsesystemet indberetter den

5. Stof, patient og medunderskriver registreres
   i jeres eget system

Nødadgang (break glass)

SnapKey har ingen særlig nødadgangsfunktion. Nødadgang planlægges derfor i beredskabet, for eksempel sådan:

Scenario: Livstruende situation kræver hurtig adgang

Procedure:
  1. Vagthavende har en nøgle med adgang til de nødvendige områder
  2. Låse markeret som kritiske sender en alarm til sikkerhed, når de bruges
  3. Åbningen logges, når låsesystemet indberetter den
  4. Efterfølgende gennemgang påkrævet

Juridisk grundlag:
  - Sundhedsloven § 42a (pligten til at yde hjælp)
  - Begrundelse dokumenteres efterfølgende

GDPR-compliance

Access logs som persondata

Access logs indeholder persondata → GDPR-krav:

✅ Legal basis: Legitim interesse (sikkerhed + compliance) ✅ Data minimization: Kun nødvendige oplysninger logges ✅ Storage limitation: Logs opbevares 5 år (jf. sundhedslovgivning) ✅ Security: Krypteret storage, access-kontrolcrypteret

Persondatapolitik-tekst

SnapKey-adgangskontrol logger:
- Navn og medarbejder-ID
- Tidspunkt for adgangsforsøg
- Lokation (hvilken dør/område)
- Resultat (adgang givet/nægtet)

Formål: Sikkerhed, compliance, revision
Opbevaring: 5 år
Deling: Ikke delt med tredjeparter
Rettigheder: Indsigtsret via HR-afdeling

Integration med EPJ-systemer

SnapKey sender hver adgangshændelse som et webhook (access.granted). Korrelationen med EPJ sker i jeres egen modtager – se Webhooks for payload og signaturkontrol:

// Correlate physical access with EPJ activity – receiver for SnapKey webhooks

app.post("/webhooks/snapkey", express.raw({ type: "application/json" }), async (req, res) => {
  // 1. Verify X-SnapKey-Signature first (see /da/docs/webhooks)
  if (!verifySnapKeySignature(req.get("X-SnapKey-Signature"), req.body.toString(), SECRET)) {
    return res.sendStatus(401);
  }
  res.sendStatus(200); // answer within 10 seconds, then do the work

  const event = JSON.parse(req.body);
  if (event.type !== "access.granted" || !event.data.person) return;

  // 2. Map the lock to a room and its current patient in your own systems
  const room = await rooms.findByLockId(event.data.lock.id);
  const patientCpr = await epj.currentPatient(room.id);

  // 3. Check if the person has the patient assigned in EPJ
  const epjAccess = await epj.checkAccessRights(event.data.person.email, patientCpr);
  if (!epjAccess.has_access) {
    await sendAlert({
      severity: "high",
      message: `${event.data.person.name} opened ${event.data.lock.name} without EPJ assignment`,
      occurred_at: event.data.occurred_at,
    });
  }

  // 4. Record the physical access in EPJ
  await epj.logPhysicalAccess(event.data.person.email, patientCpr, event.data.occurred_at);
});

FAQ

Hvordan sikres adgang ved strømsvigt?

iLOQ S5-låse er batterifrie og fungerer uden strøm. Backup-nøgler opbevares i sikret lokation. Nødgenerator til kritiske områder.

Kan SnapKey integreres med vores eksisterende badge-system?

Ja, SnapKey kan fungere parallelt med eksisterende systemer eller helt erstatte dem. API-integration med de fleste badge-systemer.


Kontakt os