Hvordan bruker jeg HelseID for overføring av attest?

HelseID skal brukes for mottak av en attest som beskrevet i Tillitsrammeverket, slik at denne kan inkluderes i et Access-token.

Termer
HelseID En autorisasjonstjener, som beskrevet i RFC 6749. Blir brukt til å sikre nasjonale API-er for helsesektoren.
Klient En klient (client) som definert i RFC 6749. I kontekst av HelseID er en klient en programvareinstallasjon som følger denne sikkerhetsprofilen.

Innsending av attest

Attesten må sendes inn som en JSON-struktur (se under).

Du kan bruke to forskjellige mønstre for å overføre attesten til HelseID:

  • Enten 1) ved å sette attesten i et Request object/Authorization Details (gjennom /authorize-endepunktet) (flyt nummer 1)

  • Eller 2) ved å sette attesten i client_assertion når klienten gjør bruk av Authorization code-parameter og/eller Refresh-token (gjennom Token-endepunktet) (flyt nummer 2)

  • Inkludering av attesten i tokens

    • Hvis attesten er sendt inn ved bruk av flyt nummer 1 (Request Object):
      • Attesten blir inkludert i alle Access-token, så lenge det korresponderende Refresh-tokenet er gyldig
      • For å oppdatere attesten, må klienten gjøre en ny forespørsel mot /Authorize-endepunktet
    • Hvis attesten er sendt inn ved bruk av flyt nummer 2 (client_assertion):
      • Attesten inkluderes i Access-token som kommer ut av denne forespørselen; ved en forespørsel mot Token-endepunktet uten attest-informasjon i client_assertion, vil attesten ikke bli satt som et claim i Access-tokenet
      • For å oppdatere attesten, må klienten gjøre en ny forespørsel mot Token-endepunktet
    • Hvis attesten er sendt inn to ganger (altså ved bruk av både flyt 1 og flyt 2), vil HelseID respondere med en feilmelding (access_denied med beskrivelses-prefikset HID-DOUBLE-STRUCTURE)

Diagrammer for flyt

Flyt nummer 1:

sequenceDiagram Ressurseier (bruker)->>Klient: Ber om pålogging via HelseID Klient->>HelseID: Gjør en forespørsel til /authorize-endepunktet, legger ved et Request-objekt som inneholder attesten HelseID->>HelseID: Validerer attesten, legger den på brukersesjonen HelseID->>Klient: Sender tilbake en respons som inneholder kode Klient->>HelseID: Gjør en forespørsel til [Token-endepunktet](/informasjonstjenester/helseid/bruksmoenstre-og-eksempelkode/bruk-av-helseid/docs/teknisk-referanse/endepunkt/token-endepunktet_no_nbmd/), ber om scopet for Tillitsrammeverk HelseID->>Klient: Sender tilbake et Access-token som inneholder attesten som et claim Klient->>KJ: Kaller (for eksempel) Kjernejournal, legger ved Access Token KJ->>KJ: Verifiserer at Access-tokenet er ment for Kjernejournal, henter (f.eks.) ut pasientens journaldokumenter KJ->>Klient: Resultat av API-kall

Flyt nummer 2:

sequenceDiagram Ressurseier (bruker)->>Klient: Ber om pålogging via HelseID Klient->>HelseID: Gjør en forespørsel til /authorize-endepunktet HelseID->>Klient: Sender tilbake en respons som inneholder kode Klient->>HelseID: Gjør en forespørsel til [Token-endepunktet](/informasjonstjenester/helseid/bruksmoenstre-og-eksempelkode/bruk-av-helseid/docs/teknisk-referanse/endepunkt/token-endepunktet_no_nbmd/), ber om scopet for Tillitsrammeverk og legger ved attesten i client_assertion HelseID->>HelseID: Validerer attesten HelseID->>Klient: Sender tilbake et Access-token som inneholder attesten som et claim Klient->>KJ: Kaller (for eksempel) Kjernejournal, legger ved Access Token KJ->>KJ: Verifiserer at Access-tokenet er ment for Kjernejournal, henter (f.eks.) ut pasientens journaldokumenter KJ->>Klient: Resultat av API-kall Note over Klient, HelseID: Klienten bruker Refresh-tokenet til å oppdatere attesten Klient->>HelseID: Gjør en forespørsel til [Token-endepunktet](/informasjonstjenester/helseid/bruksmoenstre-og-eksempelkode/bruk-av-helseid/docs/teknisk-referanse/endepunkt/token-endepunktet_no_nbmd/) med Refresh-tokenet, ber om scopet for Tillitsrammeverk og legger ved attesten i client_assertion HelseID->>HelseID: Validerer attesten HelseID->>Klient: Sender tilbake et Access-token som inneholder attesten som et claim Klient->>KJ: Kaller (for eksempel) Kjernejournal, legger ved Access Token KJ->>KJ: Verifiserer at Access-tokenet er ment for Kjernejournal, henter (f.eks.) ut pasientens journaldokumenter KJ->>Klient: Resultat av API-kall

Hva sender klienten inn, og hva valideres?

  • Klienten sender inn en nedskalert versjon av attesten: for at HelseID ikke skal trenge å validere navn på kodeverk og assigner/authority for kodeverk, så skal ikke klienten sende inn disse parametrene; HelseID utvider i stedet attesten med disse parametrene.
  • Dette innebærer også at klienten ikke skal sende inn:
    • helsepersonellets fødselsnummer og navn (practitioner:identifier)
    • helsepersonellets HPR-nummer (practitioner:hpr-nr)
  • Klienten skal foreløpig heller ikke sende inn pasientinformasjon i attesten (patients:identifier). Denne informasjonen må klienten sende inn i innholdet i et POST-kall til API-et som skal konsumeres. Det arbeides med å finne en løsning som skal gjøre det mulig å kunne sende inn pasientinformasjon gjennom attesten.
  • Kategorien patients må struktureres som et JSON-array, men som følge av at det ikke går an å sende inn pasientinformasjon, vil det foreløpig bare kunne sendes inn ett opbjekt i dette arrayet.

Obligatoriske elementer i attesten

Ikke alle elementene i attesten er obligatoriske, men klienten sende inn følgende felter i attesten:

Kategori Attributt Felter
type nhn:tillitsrammeverk:parameters N/A
practitioner legal_entity id, system
practitioner point_of_care id, system
care_relationship healthcare_service code, system
care_relationship decision_ref id, user_selected
patients (tomt element)

Ikke-obligatoriske elementer i attesten

Kategori Attributt Felter
practitioner authorization code, system
practitioner department id, system
care_relationship purpose_of_use code, system
care_relationship purpose_of_use_details code, system
patients point_of_care id, system
patients department id, system

Eksempel på en minimal struktur i JSON-format (kun obligatoriske felter):

{
    "type": "nhn:tillitsrammeverk:parameters",
    "practitioner": {
        "legal_entity": {
            "id": "946469045",
            "system": "urn:oid:2.16.578.1.12.4.1.4.101"
        },
        "point_of_care": {
            "id": "983658776",
            "system": "urn:oid:2.16.578.1.12.4.1.4.101"
        }
    },
    "care_relationship": {
        "healthcare_service": {
            "code": "S03",
            "system": "urn:oid:2.16.578.1.12.4.1.1.8655"
        },
        "decision_ref": {
            "id": "30F4AB40-DBC2-41A7-8AC4-181AD3FDC25B",
            "user_selected": true
        }
    },
    "patients": [{}]
}

Eksempel på en komplett struktur i JSON-format:

{
    "type": "nhn:tillitsrammeverk:parameters",
    "practitioner": {
        "authorization": {
            "code": "AA",
            "system": "urn:oid:2.16.578.1.12.4.1.1.9060"
        },
        "legal_entity": {
            "id": "946469045",
            "system": "urn:oid:2.16.578.1.12.4.1.4.101"
        },
        "point_of_care": {
            "id": "983658776",
            "system": "urn:oid:2.16.578.1.12.4.1.4.101"
        },
        "department": {
            "id": "4206043",
            "system": "urn:oid:2.16.578.1.12.4.1.4.102"
        }
    },
    "care_relationship": {
        "healthcare_service": {
            "code": "S03",
            "system": "urn:oid:2.16.578.1.12.4.1.1.8655"
        },
        "purpose_of_use": {
            "code": "TREAT",
            "system": "urn:oid:2.16.840.1.113883.1.11.20448"
        },
        "purpose_of_use_details": {
            "code": "15",
            "system": "urn:oid:2.16.578.1.12.4.1.1.9151"
        },
        "decision_ref": {
            "id": "30F4AB40-DBC2-41A7-8AC4-181AD3FDC25B",
            "user_selected": true
        }
    },
    "patients": [
        {
            "point_of_care": {
                "id": "983658776",
                "system": "urn:oid:2.16.578.1.12.4.1.4.101"
            },
            "department": {
                "id": "4206043",
                "system": "urn:oid:2.16.578.1.12.4.1.4.102"
            }
        }
    ]
}

Validering av innholdet i attesten

HelseID validerer innholdet i attesten i flere steg:

  1. HelseId sjekker at klienten har en godkjent tilgang til Tillitsrammeverket
  2. HelseId parser JSON-strukturen i attesten og validerer at det er en godkjent JSON-struktur
  3. HelseId gjør en gjennomgang av strukturen i attestens JSON-innhold og sjekker at strukturen matcher modellen for Tillitsrammeverket
  4. HelseId gjør en gjennomgang av innholdet i attesten og sjekker at innholdet i feltene er i korrespondanse med modellen for Tillitsrammeverket

Hvis attesten ikke blir validert, vil en av følgende feilkoder bli returnert i error_description-elementet i meldingen fra HelseID:

Prefiks i beskrivelse av feilmelding Feilmeldingskontekst
HID-JSON JSON-struktuen i attesten kunne ikke parses, eller var for lang
HID-TYPE JSON-struktuen inneholdt ingen gjenkjennbar type
HID-AUTH HelseID-klienten har manglende autorisasjon for forespørselen
HID-STRUCTURE Feil JSON-struktur i attesten; uønskede eller manglende JSON-noder ble observert
HID-CONTENT Feil innhold i attesten; feil system og/eller innholdet matcher ikke systemet
HID-GRANT Klienten har bruk en feil grant-type (flyt) i kallet til HelseID
HID-DOUBLE-STRUCTURE Klienten har sendt inn attest-struktur både som Request Object og som element i client_assertion

Eksempel på en (URL-kodet) feilmelding fra HelseID:

{
      "error":"invalid_request",
      "error_description":"HID-CONTENT: The JSON content could not be validated.\nAt node \u0027$.practitioner_role.organization.identifier.value\u0027: The child organization sent in the request is not present in the child organization whitelist for the client with client_id = \u0027helseid-sample-client-credentials-with-underenhet\u0027. Please check that this organization number has been set for the client in HelseID Selvbetjening."
},

Utvidelse av innholdet i attesten

Etter at en attest har blitt validert, vil HelseID berike innholdet i attesten. Dette fører til at Access-tokenet får et innhold som korresponderer med informasjonsmodellen i Tillitsrammeverket. Det nye innholdet inkluderer blant annet informasjon om bruker (fødselsnummer og hpr-nummer) og navn på kodeverk og verdi for hvert informasjonselement.

DPoP

Tillitsrammeverket krever at klienten som har fått utlevert en attest gjennom HelseID, også bruker DPoP / Demonstrating Proof of Possession for å sikre at tokenet ikke lett kan bli stjålet.

PAR

Tillitsrammverket krever at før en klient ber om å få utlevert en attest gjennom HelseID, skal den bruke mekanismen PAR / Pushed Authorization Requests. Denne mekanismen er satt opp for å sikre integritet og konfidensialitet for informasjonsinnholdet som sendes fra klienten til HelseID.

Overføring av attest via Authorization Details i et Request Object (flyt 1)

HelseID har støtte for RFC 9396 - Rich Authorization Requests og en klient kan overføre attesten som en verdi med å bruke denne mekanismen. Type skal da settes til nhn:tillitsrammeverk:parameters, og hele attesten inkludert type inkluderes som et element i authorization_details-arrayet. Et eksempel på et request object med en komplett authorization_details struktur er vist under:

{
  "aud": "https://helseid-sts.test.nhn.no",
  "iss": "client id her",
  ...
  "authorization_details": [{
     "type": "nhn:tillitsrammeverk:parameters",
     "practitioner": {
       ...
     },
     "care_relationship": {
       ...
     },
     "patients": [{
       ...
     }] 
   }]
}

Overføring av attest via Client Assertion (flyt 2)

Før utlevering av tokens må alle HelseID-klienter autentisere seg med bruk av en Client Assertion RFC 7523. Dette er en mekanisme der klienten signerer en JWT med sin privatnøkkel, HelseID kan da autentisere klienten ved å verifisere signaturen med en offentlig nøkkel som er knyttet til klienten.

I tillegg til standardinnholdet i en Client Assertions støtter HelseID at klienten legger ved utvidet informasjon på samme måte som når man bruker Authorization Details. Informasjonen struktureres på akkurat samme måte, men i stedet for å bruke navnet authorization_details bruker man navnet assertion_details.

Et eksenmpel på en client assertion med en assertion_details-struktur er vist under:

{
  ...
  "assertion_details": [{
     ... som over ...
   }]
}