Overview of how audit and provenance data is expected to be transported over the Visitors and Migrants FHIR interfaces.

Cross Organisation Audit & Provenance

Consumer systems SHALL provided audit and provenance details in the HTTP authorization header as an oAuth bearer token (as outlined in RFC 6749) in the form of a JSON Web Token (JWT) as defined in RFC 7519.

An example such an HTTP header is given below:

     Authorization: Bearer jwt_token_string

In future, national authentication and authorisation services will be made available which will issue a bearer token which can be used directly for accessing this API. In the interrim however, the client will need to construct the JWT themselves.

It is highly recommended that standard libraries are used for creating the JWT as constructing and encoding the token manually may lead to issues with parsing the token in Spine. A good source of information about JWT and libraries to use can be found on the JWT.io site

JSON Web Tokens (JWT)

Consumer system SHALL generate a new JWT for each API request. The Payload section of the JWT (see “JWT Generation” below for futher details) shall be populated as follows:

Claim Priority Description Fixed Value Dynamic Value Specification / Example
iss R Client systems issuer URI No Yes  
sub R ID for the user on whose behalf this request is being made. Matches requesting_practitioner .identifier.value No Yes  
aud R Authorization server’s token_URL https://authorize .fhir.nhs.uk/token No  
exp R Expiration time integer after which this authorization MUST be considered invalid. exp (now + 5 minutes) UTC time in seconds  
iat R The UTC time the JWT was created by the requesting system iat now UTC time in seconds  
reason_for_request R Purpose for which access is being requested directcare No  
requested_record R The FHIR patient resource being requested (i.e. NHS Number identifier details) No FHIR Patient1 Audit-Patient-1 (Rendered) (json) (Example)
requested_scopes R Data being requested patient/Observation.read No  
requesting_device R FHIR device resource making the request No FHIR Device1 Audit-Device-1 (Rendered) (json) (Example)
requesting_organization R FHIR organisation resource making the request No FHIR Organization1+3 Audit-Organization-1 (Rendered) (json) (Example)
requesting_practitioner R FHIR practitioner resource making the request No FHIR Practitioner2+3 Audit-Practitioner-1 (Rendered) (json) (Example - smartcard)
(Example - non-smartcard)

1 Minimal FHIR resource to include any relevant business identifier(s).

2 To contain the practitioners SDS Role profile ID (taken from their SAML assertion, linked to their Smartcard session).

3The requesting organisation resource SHALL refer to the care organisation from where the request originates rather than any other organisation which may host hardware or software, route requests to Spine, and/or hold the endpoint registration.

JWT Generation

Consumer systems SHALL generate the JSON Web Token (JWT) consisting of three parts seperated by dots (.), which are:

  • Header
  • Payload
  • Signature

The Spine does not currently validate the signature in the JWT that is sent, so the Consumer systems MAY generate an Unsecured JSON Web Token (JWT) using the “none” algorithm parameter in the header to indicate that no digital signature or MAC has been performed (please refer to section 6 of RFC 7519 for details).

{
  "alg": "none",
  "typ": "JWT"
}

If using unsigned tokens, the consumer systems SHALL generate an empty signature.

The final output is three Base64 strings separated by dots (note - there is some canonicalisation done to the JSON before it is base64 encoded, which the JWT code libraries will do for you).

For example:

eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJodHRwOi8vZWMyLTU0LTE5NC0xMDktMTg0LmV1LXdlc3QtMS5jb21wdXRlLmFtYXpvbmF3cy5jb20vIy9zZWFyY2giLCJzdWIiOiIxIiwiYXVkIjoiaHR0cHM6Ly9hdXRob3JpemUuZmhpci5uaHMubmV0L3Rva2VuIiwiZXhwIjoxNDgxMjUyMjc1LCJpYXQiOjE0ODA5NTIyNzUsInJlYXNvbl9mb3JfcmVxdWVzdCI6ImRpcmVjdGNhcmUiLCJyZXF1ZXN0ZWRfcmVjb3JkIjp7InJlc291cmNlVHlwZSI6IlBhdGllbnQiLCJpZGVudGlmaWVyIjpbeyJzeXN0ZW0iOiJodHRwOi8vZmhpci5uaHMubmV0L0lkL25ocy1udW1iZXIiLCJ2YWx1ZSI6IjkwMDAwMDAwMzMifV19LCJyZXF1ZXN0ZWRfc2NvcGUiOiJwYXRpZW50LyoucmVhZCIsInJlcXVlc3RpbmdfZGV2aWNlIjp7InJlc291cmNlVHlwZSI6IkRldmljZSIsImlkIjoiMSIsImlkZW50aWZpZXIiOlt7InN5c3RlbSI6IldlYiBJbnRlcmZhY2UiLCJ2YWx1ZSI6IkdQIENvbm5lY3QgRGVtb25zdHJhdG9yIn1dLCJtb2RlbCI6IkRlbW9uc3RyYXRvciIsInZlcnNpb24iOiIxLjAifSwicmVxdWVzdGluZ19vcmdhbml6YXRpb24iOnsicmVzb3VyY2VUeXBlIjoiT3JnYW5pemF0aW9uIiwiaWQiOiIxIiwiaWRlbnRpZmllciI6W3sic3lzdGVtIjoiaHR0cDovL2ZoaXIubmhzLm5ldC9JZC9vZHMtb3JnYW5pemF0aW9uLWNvZGUiLCJ2YWx1ZSI6IltPRFNDb2RlXSJ9XSwibmFtZSI6IkdQIENvbm5lY3QgRGVtb25zdHJhdG9yIn0sInJlcXVlc3RpbmdfcHJhY3RpdGlvbmVyIjp7InJlc291cmNlVHlwZSI6IlByYWN0aXRpb25lciIsImlkIjoiMSIsImlkZW50aWZpZXIiOlt7InN5c3RlbSI6Imh0dHA6Ly9maGlyLm5ocy5uZXQvc2RzLXVzZXItaWQiLCJ2YWx1ZSI6IkcxMzU3OTEzNSJ9LHsic3lzdGVtIjoibG9jYWxTeXN0ZW0iLCJ2YWx1ZSI6IjEifV0sIm5hbWUiOnsiZmFtaWx5IjpbIkRlbW9uc3RyYXRvciJdLCJnaXZlbiI6WyJHUENvbm5lY3QiXSwicHJlZml4IjpbIk1yIl19fX0.

NOTE: As this is an unsigned token, the final section (the signature) is empty, so the JWT will end with a trailing . - this must not be omitted as it will then not be a valid token.

JWT Payload Example

{
	"iss": "https://[ConsumerSystemURL]",
	"sub": "[PractitionerID]",
	"aud": "https://authorize.fhir.nhs.uk/token",
	"exp": 1469436987,
	"iat": 1469436687,
	"reason_for_request": "directcare",
	"requested_record": {
		"resourceType": "Patient",
		"identifier": [{
			"system": "https://fhir.nhs.uk/Id/nhs-number",
			"value": "[NHSNumber]"
		}]
	},
	"requested_scopes": "patient/*.read",
	"requesting_device": {
		"resourceType": "Device",
		"id": "[DeviceID]",
		"identifier": [{
			"system": "[DeviceSystem]",
			"value": "[DeviceID]"
		}],
		"type": "[SNOMEDCTCodeForTypeOfDevice]",
		"model": "[SoftwareName]",
		"version": "[SoftwareVersion]"
	},
	"requesting_organization": {
		"resourceType": "Organization",
		"id": "[OrganizationID]",
		"identifier": [{
			"system": "https://fhir.nhs.uk/Id/ods-organization-code",
			"value": "[ODSCode]"
		}],
		"name": "Requesting Organisation Name"
	},
	"requesting_practitioner": {
		"resourceType": "Practitioner",
		"id": "[PractitionerID]",
		"identifier": [{
			"system": "https://fhir.nhs.uk/sds-role-profile-id",
			"value": "[SDSRoleProfileID]"
		}]
	}
}

Example Code

C#

Tags: