Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: specify version for attachment functionality #72

Merged
merged 5 commits into from
Jun 17, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 22 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ const POST_URI = 'https://my-domain.com/submissions'
// Your form's secret key downloaded from FormSG upon form creation
const formSecretKey = process.env.FORM_SECRET_KEY

// Set to true if you need to download and decrypt attachments from submissions
const HAS_ATTACHMENTS = false

app.post(
'/submissions',
// Endpoint authentication by verifying signatures
Expand All @@ -62,13 +65,12 @@ app.post(
// Parse JSON from raw request body
express.json(),
// Decrypt the submission
function (req, res, next) {
const submission = formsg.crypto.decrypt(
formSecretKey,
// If `verifiedContent` is provided in `req.body.data`, the return object
// will include a verified key.
req.body.data
)
async function (req, res, next) {
// If `verifiedContent` is provided in `req.body.data`, the return object
// will include a verified key.
const submission = HAS_ATTACHMENTS
? await formsg.crypto.decryptWithAttachments(formSecretKey, req.body.data)
: formsg.crypto.decrypt(formSecretKey, req.body.data)

// If the decryption failed, submission will be `null`.
if (submission) {
Expand All @@ -79,42 +81,6 @@ app.post(
}
)

// Example for submissions with attachments
app.post(
'/submissions-attachment',
// Endpoint authentication by verifying signatures
function (req, res, next) {
try {
formsg.webhooks.authenticate(req.get('X-FormSG-Signature'), POST_URI)
// Continue processing the POST body
return next()
} catch (e) {
return res.status(401).send({ message: 'Unauthorized' })
}
},
// Parse JSON from raw request body
express.json(),
// Decrypt the submission and attachments
async function (req, res, next) {
const submission = formsg.crypto.decryptWithAttachments(
formSecretKey,
// If `verifiedContent` is provided in `req.body.data`, the return object
// will include a verified key.
req.body.data
)

// If the decryption failed at any point, submission will be `null`.
if (submission) {
// Continue processing the submission

// processSubmission(submission.content)
// processAttachments(submission.attachments)
} else {
// Could not decrypt the submission
}
}
)

app.listen(8080, () => console.log('Running on port 8080'))
```

Expand All @@ -126,12 +92,12 @@ The underlying cryptosystem is `x25519-xsalsa20-poly1305` which is implemented b

### Format of Submission Response

| Key | Type | Description |
| ---------------- | ------ | ----------------------------------- |
| formId | string | Unique form identifier. |
| submissionId | string | Unique response identifier, displayed as 'Response ID' to form respondents |
| encryptedContent | string | The encrypted submission in base64. |
| created | string | Creation timestamp. |
| Key | Type | Description |
| ---------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------- |
| formId | string | Unique form identifier. |
| submissionId | string | Unique response identifier, displayed as 'Response ID' to form respondents |
| encryptedContent | string | The encrypted submission in base64. |
| created | string | Creation timestamp. |
| attachmentDownloadUrls | Record<string, string> | (Optional) Records containing field IDs and URLs where encrypted uploaded attachments can be downloaded. |

### Format of Decrypted Submissions
Expand Down Expand Up @@ -190,19 +156,20 @@ If the decrypted content is the correct shape, then:

### Processing Attachments

`formsg.crypto.decryptWithAttachments(formSecretKey: string, decryptParams: DecryptParams)` behaves similarly except it will return a `Promise<DecryptedContentAndAttachments | null>`.
`formsg.crypto.decryptWithAttachments(formSecretKey: string, decryptParams: DecryptParams)` (available from version 0.9.0 onwards) behaves similarly except it will return a `Promise<DecryptedContentAndAttachments | null>`.

`DecryptedContentAndAttachments` is an object containing two fields:

`DecryptedContentAndAttachments` is an object containing two fields:
- `content`: the standard form decrypted responses (same as the return type of `formsg.crypto.decrypt`)
- `attachments`: A `Record<string, DecryptedFile>` containing a map of field ids of the attachment fields to a object containing the original user supplied filename and a `Uint8Array` containing the contents of the uploaded file.
- `content`: the standard form decrypted responses (same as the return type of `formsg.crypto.decrypt`)
- `attachments`: A `Record<string, DecryptedFile>` containing a map of field ids of the attachment fields to a object containing the original user supplied filename and a `Uint8Array` containing the contents of the uploaded file.

If the contents of any file fails to decrypt or there is a mismatch between the attachments and submission (e.g. the submission doesn't contain the original file name), then `null` will be returned.

Attachments are downloaded using S3 pre-signed URLs, with a expiry time of *one hour*. You must call `decryptWithAttachments` within this time window, or else the URL to the encrypted files will become invalid.
Attachments are downloaded using S3 pre-signed URLs, with a expiry time of _one hour_. You must call `decryptWithAttachments` within this time window, or else the URL to the encrypted files will become invalid.

Attachments are end-to-end encrypted in the same way as normal form submissions, so any eavesdropper will not be able to view form attachments without your secret key.

*Warning:* We do not have the ability to scan any attachments for malicious content (e.g. spyware or viruses), so careful handling is neeeded.
_Warning:_ We do not have the ability to scan any attachments for malicious content (e.g. spyware or viruses), so careful handling is needed.

## Verifying Signatures Manually

Expand Down