# SHCLinks: GNAP Sketch
## Background and Design goals
See https://hackmd.io/kvyVFD5cQK2Bg1_vnXSh_Q
See https://datatracker.ietf.org/doc/draft-ietf-gnap-core-protocol/ protocol for reference
## Design Sketch #3: GNAP Method
### GNAP Method: Software components
* **Resource Server**. Hosts static files (which can be updated over time). These files are (may be?) encrypted so the resource server can't read them.
* **Authorization Server**. Manages access control for files in the Resource Server. The Authorization Server is also blind to the contents of encrypted static files.
^^These servers can be packaged together into a single software release, but they don't need to be.
### GNAP Method: Workflow
* **Generate Shared File(s)**. Data Sharer chooses or creates files to share; encrypts them with a new symmetric key; uploads them to the resource server; and registers the set of uploaded files with the authorization server. The files can be FHIR Bundles in which resources are optionally signed; or can be `.smart-health-card` JSON files. Creating and uploading the files can be a manual step performed by the Data Sharer using an offline (e.g., phone-based) app, or it can be an automated step performed on behalf of the Data Sharer by a cloud-hosted health records agent. Details are out of scope.
* **Generate a QR Link**. User asks authorization server to generate a QR with a link to the files. This is encoded as a `shclink:/[0-9]+` URI, building on conventions from the SMART Health Cards spec. The QR is configured at generation time to be:
* associated with a specific access endpoint and files
* (optional). limited to being "claimed" with a PIN (e.g., random 4-digit code or patient demographics such as birthdate)
* (optional). limited to being "claimed" only once
* (optional). limited to a specific "access period"
* **Share the QR Link**. Data Sharer allows a Data Recipient to scan the QR code.
* **Claim the QR Link**. Data Recipient "claims" a link. This means that the recipient trades the link for an access token that can be used to retrieve a file. During this process, the recipient may need to demonstrate knowledge of a PIN, or perform other steps to meet conditions of the sharing policy. (Note: A QR Link may be configured such that it can be claimed only once, or it may allow multiple recipients to claims it.)
* **Resolve the QR Link**. Data Recipient uses their access token to resolve the QR Link, retrieving the shared files and then decrypting them. This step happens once up-front, and MAY happen periodically (e.g., each week an school may request updated COVID-19 PCR results for a student).
* **Optional: Update Shared Files**. For some sharing scenarios, the Data Sharer MAY update the shared files from time to time (e.g., when new lab results arrive or new immunizations are performed). Updated verions SHALL be encrypted using the same key (if any) as the initial version.
### GNAP Method: Protocol details
:::danger
**Warning**. These details are not at all pinned down; there's the sketch of an implementation at https://github.com/jmandel/shclinks
:::
The QR is encoded as follows
1. Create a QR Link JSON Payload (cleartext, no signature)
2. Minify
3. DEFLATE
4. Apply SHC numeric encoding
5. Prepend `shclink:/`
#### GNAP Method: QR Link JSON Payload
* `gnap`: GNAP protocol interaction details. A JSON object.
* `url`: URL for the authorization server. A string starting with `https://`.
* `access`: GNAP access reference. An string, opaque to the client, high-entropy, from 16 to 800 characters long. (This MAY be a JWS or any other format the authorization server prefers; the value created and consumed by the authorization server, and merely passed along by the client.)
* `exp`: Optional. Expiration time in Epoch seconds. Hint to help the Data Recipient determine if this QR is stale.
* `flags`: Optional. String created by concatenating single-character flags in alphabetical order
* `L` for long-term use
* `O` for one-time-use
* `P` if a receiver-supplied PIN is required for redemption
* `decrypt`: Conditional. Omitted if the target resource is not encrypted. Included otherwise. This key can be used to decrypt the target file. (?Format: base64urlencoded 256-bit random string? This field is necessary if we want to support encrypting files so that the resource server and authorization sever can't read them.)
:::warning
**Questions**. How can the resource server rotate or add to its keys for communicating with the authz server? How can the data recipient do the same? Does GNAP envision this with JWK-based auth?
:::
#### GNAP Method: Claiming a QR Link
The claiming mechanism allows a QR to be short-lived, while data access remains long-lived.
The process for getting an acess token follows IETF's draft GNAP protocol. The Data Recipient generates a keypair for this request, which proceeds following https://www.ietf.org/archive/id/draft-ietf-gnap-core-protocol-07.html#name-software-only-authorization.
```json=
{
"access_token": {
"access": [`${jsonPayload.gnap.access}`]
},
"client": {
"key": {
"proof": "jws",
"jwk": {...clientJwk}
}
}
}
```
This request body is signed by the Data Recipient's client, following https://www.ietf.org/archive/id/draft-ietf-gnap-core-protocol-07.html#name-attached-jws. The resulting token is submitted to the authorization server:
POST `${jsonPayload.gnap.url}`
The authorization response looks like:
```json=
{
"access_token": {
"value": "some-opaque-high-entropy-string-123",
"access": [{
"type": "https://smarthealth.cards/qrlink",
"locations": [
"https://resources.example.org/path/to/my.smart-health-card",
// more array entries can provide access to more data of the same time
],
"datatypes": [
"application/smart-health-card",
]
}] // more array entries can provide access to additional data types
}
}
```
#### GNAP Method: Downloading a file
The client issues a GET on any `access_token.access[].locations[]`, following https://www.ietf.org/archive/id/draft-ietf-gnap-core-protocol-07.html#name-attached-jws to create a JWS signature on each request.
The client may re-issue the GET periodically if the original QR-link included the `L` flag for long-term use. When making long-term request, the client refreshes expired access tokens per https://www.ietf.org/archive/id/drafta-ietf-gnap-core-protocol-07.html#name-refreshing-an-expired-acces.
#### GNAP Method: Revoking Access
The authorization server allows a Data Sharer to review outstanding shares, see whether (and how often) they're being used, and revoke access at any time.