This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

DSR-RFC-09 Health Service API

    Structure of the Health Service

    A concrete instance of a FD service is identified via FQDN

    Application / ServiceProviderFQDN
    DSR “dummy” health servicetbddsr.health-service.example.com

    The DSR “dummy” health service provides the following business APIs / resources

    APIVersionURL
    emergency data APIv1https://dsr.health-service.example.com/api/v1/notfalldaten
    ePrescription APIv1https://dsr.health-service.example.com/api/v1/erezept/
    ePrescription APIv2https://dsr.health-service.example.com/api/v2/erezept/

    Scaling and load balancing is done in the background, invisible to the clients.

    API Documentation

    see poc-dsr-fd on GitHub.

    Test Data ePrescription API

    VersionID
    v16c371ed4-f83a-47b4-8249-446852a5b382
    v117e5970d-6e64-465f-be0c-ed0f5d7624a0
    v200fa65b9-2e07-40c7-b8c5-fadf549c4ed7
    v201e18e40-83a5-4986-819f-c68c2227b59d

    Test Data emergency data API

    patientIdentifier
    X123456
    X234567
    X345678

    Input Data for Policy Decision Point

    Input data for access decisions by the Policy Decision Point is independent of the DSR “dummy” health Service or its APIs and results from the external sources. The Policy Enforcement Point is responsible to determine appropriate input, verify and submit to the Policy Decision Point for decision according to a JSON schema:

    Input Example for iOS Devices

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    {
      "request": {
        "method": "GET",
        "path": "/api/v1/notfalldaten",
        "clientIP": "XXX.XXX.XXX.XXX",
        "countryCode": "DE"
      },
      "deviceTokenValid": true,
      "deviceTokenPayload": {
        "type": "IOS",
        "userIdentifier": "X114428530",
        "deviceHealth": {
          "assertion": {integrityVerdict         "counter": 1,
            "rpID": "XXXXXX",
            "riskMetric": "unavailable"
          },
          "deviceAttributes": {
            "systemVersion": "16.6",
            "systemName": "iOS",
            "identifierForVendor": "XXXXXX",
            "systemModel": "iPhone13,3"
          }
        },
        "iss": "DSR GMS 1.0.0",
        "sub": "XXXX",
        "iat": 1234567890,
        "exp": 1234567890,
        "cnf": {
          "x5t#S256": "XXXXXX"
        },
        "jti": "XXXXXX"
      }
    }
    

    Input Example for Android Devices

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    
    {
      "request": {
        "method": "GET",
        "path": "/api/v1/notfalldaten",
        "clientIP": "XXX.XXX.XXX.XXX",
        "countryCode": "DE"
      },
      "deviceTokenValid": true,
      "deviceTokenPayload": {
        "type": "ANDROID",
        "userIdentifier": "TEST KVNR",
        "deviceHealth": {
          "integrityVerdict": {
            "appIntegrity": {
              "appRecognitionVerdict": "UNRECOGNIZED_VERSION",
              "packageName": "de.gematik.dsr.android",
              "certificateSha256Digest": [
                "XXXXXX"
              ],
              "versionCode": 1
            },
            "deviceIntegrity": {
              "deviceRecognitionVerdict": [
                "MEETS_DEVICE_INTEGRITY"
              ]
            },
            "accountDetails": {
              "appLicensingVerdict": "UNLICENSED"
            }
          },
          "keyIdAttestation": {
            "attestationVersion": 200,
            "attestationSecurityLevel": 1,
            "softwareEnforced": {
              "creationDateTime": "2023-07-24T10:59:02.933Z",
              "usageExpireDateTime": "2024-07-23T12:59:02Z",
              "activeDateTime": "2023-07-24T09:59:02Z",
              "attestationApplicationId": {
                "packageInfos": [
                  {
                    "packageName": "de.gematik.dsr.android",
                    "version": 1
                  }
                ],
                "signatureDigests": [
                  "XXXXXX"
                ]
              },
              "rootOfTrust": null,
              "originationExpireDateTime": "2024-07-23T12:59:02Z"
            },
            "teeEnforced": {
              "purpose": [
                2,
                3
              ],
              "attestationIdDevice": "XXXXXX",
              "keySize": 256,
              "osVersion": 130000,
              "origin": 0,
              "osPatchLevel": 202306,
              "attestationIdModel": "XXXXXX",
              "attestationIdProduct": "XXXXXX",
              "vendorPatchLevel": 20230605,
              "attestationApplicationId": null,
              "noAuthRequired": true,
              "rootOfTrust": {
                "verifiedBootKey": "XXXXXX",
                "deviceLocked": true,
                "verifiedBootState": "VERIFIED",
                "verifiedBootHash": "XXXXXX"
              },
              "algorithm": 3,
              "digest": [
                4
              ],
              "ecCurve": 1,
              "attestationIdManufacturer": "XXXXXX",
              "attestationIdBrand": "XXXXXX",
              "bootPatchLevel": 20230605
            },
            "keyStore": {
              "type": "KEY_MINT",
              "version": 200,
              "securityLevel": 1
            }
          },
          "deviceAttributes": {
            "build": {
              "version": {
                "sdkInit": 33,
                "securityPatch": "2023-06-05"
              },
              "manufacturer": "Google",
              "product": "oriole",
              "model": "Pixel 6",
              "board": "oriole"
            },
            "ro": {
              "crypto": {
                "state": true
              },
              "product": {
                "firstAPILevel": 31
              }
            },
            "packageManager": {
              "featureVerifiedBoot": true
            },
            "keyguardManager": {
              "isDeviceSecure": true
            },
            "biometricManager": {
              "deviceCredential": true,
              "biometricStrong": true
            },
            "devicePolicyManager": {
              "passwordComplexity": 327680
            }
          }
        },
        "iss": "DSR GMS 1.0.0",
        "sub": "XXXXXX",
        "iat": 1234567890,
        "exp": 1234567890,
        "cnf": {
          "x5t#S256": "XXXXXX"
        },
        "jti": "XXXXXX"
      }
    }
    

    The structural check of the device token (signature, validity, mTLS fingerprint matching) is performed in the Policy Enforcement Point before the Policy Decision Point is called. The result of this check is passed to the Policy Decision Point with the deviceTokenValid attribute.

    Access Decision / Verdict by the PDP

    For example, the positive decision look like this:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    {
      "allow": true,
      "device": {
        "allow": true,
        "violations": []
      },
      "security": {
        "allow": true,
        "violations": []
      }
    }
    

    A negative decision provides hints about which checks failed and looks like the following examples:

    Failed Android Device

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
    {
      "allow": false,
      "device": {
        "allow": false,
        "violations": [
          {
            "error": "device_android_api_level_violation",
            "error_description": "Device is required to have API level 33 or higher. Current API level: 11."
          },
          {
            "error": "device_android_encryption_disabled",
            "error_description": "Device is required to have encryption enabled."
          },
          {
            "error": "device_android_patch_level_violation",
            "error_description": "Device is required to have patchlevel 2022-12-01 or higher. Current patch level: 2019-01-01."
          },
          {
            "error": "device_unknwown_app",
            "error_description": "App is not approved by gematik."
          }
        ]
      },
      "security": {
        "allow": true,
        "violations": []
      }
    }
    

    Failed iOS Device

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    {
      "allow": false,
      "device": {
        "allow": false,
        "violations": [
          {
            "error": "device_ios_invalid_version",
            "error_description": "Device is required to have iOS 14.0.0 or higher. Current version: 13.0.0."
          },
          {
            "error": "device_unknown_app",
            "error_description": "App is not approved by gematik."
          }
        ]
      },
      "security": {
        "allow": true,
        "violations": []
      }
    }