Versions Compared

Key

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

Using JSON Web Tokens (JWTs) to secure your APIs has become an ad-hoc standard in the IT-industry. However, the underlying concepts and mechanisms can be complex and are often misunderstood.

The general advice below pertains to both clients (id tokens) and API-s (access tokens). The specific guidelines regarding access tokens should be followed by API providers.

Info

General advice when using JWTs

  • Using JWTs to handle sessions introduces new risks. Allways Always do a thorough risk assessment before you deploy to your production environment.

  • Using JWTs assumes that all involved secrets are handled in a proper way in both API-clients and APIs. Secrets could be both passwords and cryptographic key material. Always make sure your secrets are kept safe!

  • Do not accept unsafe JWTs with the JOSE header {"alg": none; }. JWTs should always be signed and should use a valid and correct signature scheme

  • If a JWT contains sensitive data it should be encrypted

Info

Things to consider when using Identity Tokens

  • Identity Tokens are meant for the client, and should not be passed on to other parties.

  • Identity Tokens should be persisted in the client to allow for an seamless sign-out experience

  • If a client also has local user identities, it should ensure that the locally signed in user is the same person as the user signing in to HelseID.

Info

Things to consider when using Access Tokens

  • A "self contained" JWT can not be revoked until it expires. Consider using referenced tokens if the token provides access to sensitive or high-risk data.

  • Access Tokens should be opaque to the client, they are meant for the API.

    • The lifetime of an access token is returned as a separate value to the client.

  • Access Tokens should have a life-time that is as short as possible.
    As a general principle: the more sensitive data an API exposes the shorter the life-time should be.

  • To enhance the user experience sessions with a long life-span should be combined with Access Tokens that have short life-span. You can acheive this by using refresh tokens on the client.

Note

Always verify the integrity of the JWT

  • Always validate the token signature

  • Make sure your libraries and frameworks always validates the token signature

  • HelseID only offers signatures based on asymmetric algorithms

Note

DO NOT BLINDLY TRUST THE VALUE IN CLAIMS

Examples:

  • “kid” - do not perform certificate requests before the values are validated and verified

  • “jku” or “x5u” are header values that point to a URL. Do NOT follow these URLs before they are validated in order to avoid SSRF attacks

Note

Always validate claims in the Access Token

  • Always verify the "exp" claim to make sure the token hasn’t expired

  • Always verify the claim "nbf" to make sure the token actually is "active"

  • When verifying claims with timestamps, take into account that there may be some time skew between the token issuer and your internal systems.

  • Always verify the claim "iss" to make sure that the token issuer is someone you actually trust

  • Always verify the claim "aud" to make sure that the token is intended for you

  • Reject the request if the "aud" claim is missing

  • Consider rejecting tokens with multiple values in the “aud” claim.

  • If you use "scopes" for access control you must always make sure that the values in the “scope” claims are valid and correct.

  • Always validate and verify that the value in the claim “helseid://claims/identity/assurance_level“, alternatively “helseid://claims/identity/security_level”, corresponds with the requirements for your API.

  • Consider validating and verifying the value in the claim "helseid://claims/identity/pid".

  • Consider validating and verifying the value in the claim "helseid://claims/hpr/hpr_number".

  • Consider validating and verifying the value in the claims containing organizational identitfiers, e.g. “helseid://claims/client/claims/orgnr_parent“ and “helseid://claims/client/claims/orgnr_child“