Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info

Dette er en teknisk bekrivelse av Token Exchange. For en overordnet beskrivelse se Token Exchange for API-eiere

Token Exchange i HelseID baserer seg på IETF-spesifikasjonen RFC 8693: OAuth 2.0 Token Exchange, som beskriver en protokoll for å hente ut tokens fra en STS for «impersonation» og «delegation».

...

av

...

Sentrale begreper

Token Exchange innfører noen nye begreper:

subject_token: Et access token utstedt av HelseID hvor det er inkludert claims om autentisert person og virksomhet. Dette tokenet veksles inn ved bruk av token exchange.

subject client: En klient som er mottaker av et subject_token.

actor client: En klient som ønsker å veksle inn subject_token ved bruk av token exchange for å få et nytt access token som kan brukes til å kalle en annen tjeneste. Denne klienten er typisk et API som må hente data fra et annet API som også er sikret med HelseID.

Protokollflyt

Overordnet flyt

  1. Subject client forespør autentisering av bruker og ber om tilgang til API A.

  2. HelseID utsteder Access Token (AT#1) med tilgang til API A.

  3. Subject client gjør et kall til API A, med AT#1 i Authorization header.

  4. API A trenger data fra API B og trenger dermed et Access Token for dette.

  5. API A gjør en Token Exchange-forespørsel mot HelseID og ber om tilgang til API B.

    • AT#1 er subject_token i denne forespørselen.

    • API A er actor client i denne forespørselen.

  6. HelseId utsteder et nytt Access Token (AT#2) og returnerer det til API A.

  7. API A gjør et kall til API B med AT#2 i Authorization header.

...

Token Exchange forespørsel

  • grant_type: alltid urn:ietf:params:oauth:grant-type:token-exchange.

  • scope: API resource scopes som ønskes. Separer scopes med mellomrom.

  • subject_token: Access Token utstedt av HelseID som skal utveksles

  • subject_token_type: alltid urn:ietf:params:oauth:token-type:access_token.

  • client_assertion: base64 enkodet signert JWT. Se Client Assertion fra actor client.

  • client_assertion_type: alltid urn:ietf:params:oauth:client-assertion-type:jwt-bearer.

Alle parametre må sendes i body som en del av en POST request.

Eksempel:

Code Block
POST /connection/token

grant_type=urn:ietf:params:oauth:grant-type:token-exchange&
scope=api1 api2&
subject_token=[base64 enkodet access token]&
subject_token_type=urn:ietf:params:oauth:token-type:access_token&
client_assertion=[base64 enkodet jwt]&
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer

Respons ved suksess

  • access_token: base64 enkodet Access Token. Dette tokenet brukes av actor client ved forespørsler til andre APIer.

  • issued_token_type: alltid urn:ietf:params:oauth:token-type:access_token.

  • token_type: alltid Bearer.

  • expires_in: levetid i sekunder for returnert token.

Eksempel:

Code Block
breakoutModewide
 HTTP/1.1 200 OK
 Content-Type: application/json
 Cache-Control: no-cache, no-store

 {
  "access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IkI0Q0FFNDUyQzhCNkE4OTNCNkE4NDBBQzhDODRGQjA3MEE0MjZFNDEiLCJ4NXQiOiJ0TXJrVXNpMnFKTzJxRUNzaklUN0J3cENia0UiLCJ0eXAiOiJKV1QifQ.
  eyJpc3MiOiJodHRwczovL2xvY2FsaG9zdDo0NDM2NiIsIm5iZiI6MTY3MzYwMjc1NSwiaWF0IjoxNjczNjAyNzU1LCJleHAiOjE2NzM2MDYzNTUsImF1ZCI6InVkZWx0OnRlc3QtYXBpIiwic2NvcGUiOlsidWRlbHQ6dGV
  zdC1hcGkvYXBpIl0sImFtciI6WyJwd2QiXSwiY2xpZW50X2lkIjoidG9rZW5fZXhjaGFuZ2VfYWN0b3JfY2xpZW50IiwiaGVsc2VpZDovL2NsYWltcy9jbGllbnQvb3JpZ2luYWxfY2xpZW50X2lkIjoidG9rZW5fZXhjaG
  FuZ2Vfc3ViamVjdF9jbGllbnQiLCJjbGllbnRfYW1yIjoicHJpdmF0ZV9rZXlfand0IiwiaGVsc2VpZDovL2NsYWltcy9pZGVudGl0eS9waWQiOiIxNTAzNzEwNDIyOSIsImhlbHNlaWQ6Ly9jbGFpbXMvaWRlbnRpdHkvc
  2VjdXJpdHlfbGV2ZWwiOiI0IiwianRpIjoiNzExMzgzRjNENEQ4NjhDMDMzOTdENzEyNTU1N0UzRjAiLCJzaWQiOiI2NzFGOEVCRUU0OEJBRDE0NjgwRUJBNEMwQzI1MDkyMCIsImFjdCI6eyJpc3MiOiJodHRwczovL2xv
  Y2FsaG9zdDo0NDM2NiIsImNsaWVudF9pZCI6InRva2VuX2V4Y2hhbmdlX2FjdG9yX2NsaWVudCIsImhlbHNlaWQ6Ly9jbGFpbXMvY2xpZW50L2NsYWltcy9vcmducl9wYXJlbnQiOiI5OTk5Nzc3NzQifSwiaGVsc2VpZDo
  vL2NsYWltcy9jbGllbnQvY2xhaW1zL29yZ25yX3BhcmVudCI6Ijk5OTk3Nzc3NCIsInN1YiI6IlVwVUFpZTNQVTZCYVgyTStTbFZWZVh5cDg2YjRQTXZOeTlpOVppMlNoVWc9IiwiYXV0aF90aW1lIjoxNjczNjAyNzQ1LC
  JpZHAiOiJ0ZXN0aWRwLW9pZGMiLCJuYW1lIjoiQU5ORSBNQVJLVVNTRU4gRU5HRUJBS0tFTiIsImhlbHNlaWQ6Ly9jbGFpbXMvY2xpZW50L2FtciI6InJzYV9wcml2YXRlX2tleSJ9.BGfYrDi6PLks_dV99SDjCsnKFytc
  kHIbh0sFVNOWF7Y75ZJVzo4xKf6CpA1AO38VnYk7PsGuM3HpSTQSpXl8IAgJ8CsZ8nTBzRponsneamxBLrcUlMcVq-CeY6NmFyUYvV-FZik7D2spEXzNdTuuPGiK7y2Ik1es0SIW_fdKDAzYi9Y06MhVE9YZJNi1OdJzCSU
  DGNKg_-2u6D18dX2Gd877VViYm0CL6_4N1LxkaKbxMM8LTwh_7Q36VzbqeQAR9sPJibGuOkdJXlJAAmm2B2WzxEU3OpscWe1zCtQ8jhnqfI9oLcD11nX5C549p_1XiL0DAbZQBQwA9P7ce_frQg",
  "issued_token_type":"urn:ietf:params:oauth:token-type:access_token",
  "token_type":"Bearer",
  "expires_in":3600
 }
 

Respons ved feil

  • error: feilkode.

  • error_description: beskrivelse av feil.

De følgende feilsituasjonene er spesifikke for token exchange:

  • Feil i validering av subject token:

    Code Block
    {
        "error": "invalid_request",
        "error_description": "invalid subject_token - [detaljert informasjon]"
    }
    

    Dette inkluderer at tokenet ikke er utstedt av HelseID, at det har utgått og annet.

  • Actor client mangler rettigheter:

    Code Block
    {
        "error": "invalid_request",
        "error_description": "not permitted"
    }
    

    Denne situasjonen oppstår dersom subject client ikke er konfigurert til å tillate token exchange for actor client.

  • Actor client spør om for brede tillatelser:

    Code Block
    {
        "error": "invalid_target",
        "error_description": "invalid scopes requested"
    }
    

    Dette oppstår dersom klienten spør om scopes som går på tvers av API-ressurser.

  • Actor client forsøker å veksle inn et token som allerede er vekslet inn for mange ganger:

    Code Block
    {
        "error": "invalid_request",
        "error_description": "subject_token exchanged too many times (5)"
    }
    
  • Actor client tilhører en annen Configuration Owner enn aud (API ressurs) i subject token:

    Code Block
    {
        "error": "invalid_request",
        "error_description": "no audience matching configuration owner of client_id [client_id] was found in subject token"
    }
    

Eksempel:

Code Block
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-cache, no-store

{
    "error": "invalid_target",
    "error_description": "invalid scopes requested"
}

Client Assertion fra actor client

Client Assertion brukes på samme måte som ved andre flyter.

En Client Assertion er en standard JWT som er bygd opp i henhold til RFC 7523.

Følgende claims må være med:

  • iss: client_id til actor client.

  • sub: client_id til actor client

  • aud: HelseID token-endepunkt. Må være likt iss i subject_token.

  • exp: tidspunkt client assertion utløper i epoch tid.

  • iat: tidspunkt for utstedelse av client assertion i epoch tid.

Merk at HelseID stiller krav om at Client Assertions ikke kan ha lenger levetid enn 60 sekunder.

I tillegg til claimene ovenfor støtter HelseID påstander knyttet til identiteten til actor client, spesifikt virksomheten som klienten opererer under. Disse claimene vil reflekteres under act claimet i Access Token som utstedes ved vellykket Token Exchange.

  • helseid://client/claims/orgnr_parent: organisasjonsnummer for hovedenhet fra actor client.

  • helseid://client/claims/orgnr_parent_description: beskrivelse av organisasjonsnummer for hovedenhet (maks 100 tegn).

  • helseid://client/claims/orgnr_child: organisasjonsnummer for underenhet fra actor client.

  • helseid://client/claims/orgnr_child_description: beskrivelse av organisasjonsnummer for underenhet (maks 100 tegn).

Eksempel på Client Assertion payload:

Code Block
{
    "exp":1541635665,
    "iat":"1541635665",
    "iss":"c26a87dd-b875-412a-a30b-4b487f141153",
    "sub":"c26a87dd-b875-412a-a30b-4b487f141153",
    "aud":"https://helseid-sts.test.nhn.no/connect/token"
    "helseid://client/claims/orgnr_parent":"912159523",
    "helseid://client/claims/orgnr_parent_description":"EKSEMPEL AS"
}

Signering av Client Assertion

Client Assertion må signeres med actor client sin hemmelighet i HelseID. HelseID støtter signering med RSA- og ECDSA-nøkkelpar.

JWT'en signeres med klientens private nøkkel. HelseID bruker deretter den offentlige nøkkelen til å verifisere signaturen og autentisere klienten.

Nøkkelpar settes opp i HelseID Selvbetjening.

Utstedt Access Token

Ved vellykket Token Exchange vil actor client få utstedt et Access Token som med følgende claims:

client_id: klient identifikator for actor client.

helseid://claims/client/original_client_id: klient identifikator fra det initielle tokenet som ble utstedt uten Token Exchange (det første subject_tokenet i kjeden).

Claims kopiert fra subject token:

  • Alle claims med prefiks helseid://

  • sub: HelseID-spesifikk identifikator for autentisert bruker.

  • idp: IDP som ble brukt i forbindelse med autentisering av bruker.

  • amr: påloggingsmetode i IDP som ble brukt i forbindelse med autentisering av bruker.

  • auth_time: tidspunkt brukeren ble autentisert.

Standard JWT claims:

  • nbf

  • exp

  • iss

  • aud

  • scope

  • jti

act: Et sett av claims som identifiserer virksomhet og klient som opptrer på vegne av en autentisert person. act claimet er bygd opp som følger:

  • iss: HelseID STS sin har identifisert actor client.

  • client_id: identifikator for actor client

  • helseid://claims/client/claims/orgnr_parent: organisasjonsnummer for hovedenhet.

  • helseid://claims/client/claims/orgnr_parent_description: beskrivelse av organisasjonsnummer for hovedenhet.

  • helseid://claims/client/claims/orgnr_child: organisasjonsnummer for underenhet.

  • helseid://claims/client/claims/orgnr_child_description: beskrivelse av organisasjonsnummer for underenhet.

Eksempel på act claim:

Code Block
{
    "iss": "https://helseid-sts.test.nhn.no",
    "client_id": "client_actor",
    "helseid://claims/client/claims/orgnr_parent": "912159523",
    "helseid://claims/client/claims/orgnr_parent_description": "EKSEMPEL AS"
}

For kallkjeder der Token Exchange benyttes flere ganger, vil man få en nøstet struktur av act claims. Den innerste actor er den eldste, og den ytterste actor er den nyeste - og altså den aktive actor for det aktuelle access token.

Eksempel på act claim med nesting:

Code Block
{
    "iss": "https://helseid-sts.test.nhn.no",
    "client_id": "client_actor_2",
    "helseid://claims/client/claims/orgnr_parent": "111111111",
    "helseid://claims/client/claims/orgnr_parent_description": "NAVN AS",
    "act": {
        "iss": "https://helseid-sts.test.nhn.no",
        "client_id": "client_actor",
        "helseid://claims/client/claims/orgnr_parent": "912159523",
        "helseid://claims/client/claims/orgnr_parent_description": "EKSEMPEL AS"
    }
}

I dette eksempelet er client_actor_2 aktiv actor, og client_actor den forrige.

Eksempel på fullstendig Access Token:

Code Block
{ "iss": "https://helseid-sts.test.nhn.no", "nbf": 1672911351, "iat": 1672911351, "exp": 1672914951, "aud": "test:test-api", "scope": [ "test:test-api/api" ], "amr": [ "pwd" ], "client_id": "[token_exchange_actor_client_guid]", "helseid://claims/client/original_client_id": "[token_exchange_subject_client_guid]", "client_amr": "private_key_jwt", "helseid://claims/identity/pid": "15037104229", "helseid://claims/identity/security_level": "4", "jti": "2E2F7052528642005005B66995E1D083", "sid": "9CC2BC2A4298DEBA9B0C5AD1BF8EC53B", "act": { "iss": "https://helseid-sts.test.nhn.no", "client_id": "token_exchange_actor_client", "helseid://claims/client/claims/orgnr_parent": "999977774" }, "helseid://claims/client/claims/orgnr_parent": "999977774", "sub": "UpUAie3PU6BaX2M+SlVVeXyp86b4PMvNy9i9Zi2ShUg=", "auth_time": 1672911347, "idp": "testidp-oidc", "name": "ANNE MARKUSSEN ENGEBAKKEN", "helseid://claims/client/amr": "rsa_private_key" }

Token Exchange se Token Exchange for API-eiere

For en teknisk dokumentasjon av Token Exchange, se dette dokumentet.