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

feat: platform api v1 - get and update webhook settings #6608

Merged
merged 16 commits into from
Aug 17, 2023

Conversation

wanlingt
Copy link
Contributor

@wanlingt wanlingt commented Aug 8, 2023

Problem

Closes FRM-1244, FRM-1242, FRM-1243

Solution

This PR implements

  • API access for admins that are also "platforms" - i.e. they perform actions on behalf of other Form admins. Examples include Plumber and EngageSG. This is represented by the new isPlatform boolean property in the apiToken object.

Ideally, authorisation would be via OAuth to allow for more fine-grained permissions, but for the purposes of the MVP, we are going with this simplified approach. Inspiration was taken from GoGovSG's admin API which allows FormSG to create shortlinks on behalf of GoGovSG admins.

  • In addition to authenticating the API key (shared with /api/public/v1), the /public/v1 route uses a middleware check isPlatformApiUser in auth.middlewares.ts. If the API user is a platform, and has provided a userEmail, it looks for the user associated with the userEmail and sets req.session.user as that user

New platform API endpoints:

  • POST /api/public/v1/admin/forms/:formId/webhooksettings to retrieve webhook settings.
  • PATCH /api/public/v1/admin/forms/:formId/webhooksettings to update webhook settings

More details can be found in the APIs design doc (WIP)

Breaking Changes

  • No - this PR is backwards compatible

Future Improvements (TODOs):

Tests

POST /api/public/v1/admin/forms/:formId/webhooksettings to retrieve webhook settings

curl --request POST \
  --url https://staging.form.gov.sg/api/public/v1/admin/forms/:formId/settings \
  --header 'Authorization: Bearer test_v1_APITOKENHERE' \
  --header 'Content-Type: application/json' \
  --data '{"userEmail": "adminOfFormId"}'
  • Test that API call works - the webhook settings retrieved should be what's in the DB. The userEmail provided should be an admin of the formId in the URL
  • Use an invalid API token. You should get a 401 Unauthorised - Invalid API Key message
  • Use a user email that is a FormSG user, but isn't the admin of the form ID provided. You should get a 403 Forbidden message
  • Use an invalid form ID. You should get a 404 not found error
  • Use an invalid request body e.g. misspell userEmail to useEmail. You should get a 400 Bad Request validation error

PATCH /api/public/v1/admin/forms/:formId/webhooksettings to update webhook settings

curl --request PATCH \
  --url https://staging.form.gov.sg/api/public/v1/admin/forms/:formId/settings \
  --header 'Authorization: Bearer test_v1_APITOKENHERE' \
  --header 'Content-Type: application/json' \
  --data '{"userEmail": "adminOfFormId",
"webhook": {
		"url":"https://www.webhookUrl.com",
	"isRetryEnabled": true
}}'
  • Test that API call successfully updates the webhook settings. The userEmail provided should be an admin of the formId in the URL
  • Use an invalid API token. You should get a 401 Unauthorised - Invalid API Key message
  • Use a user email that is a FormSG user, but isn't the admin of the form ID provided. You should get a 403 Forbidden message
  • Use an invalid form ID. You should get a 404 not found error
  • Use an invalid request body e.g. misspell userEmail to useEmail. You should get a 400 Bad Request validation error

Deploy Notes

New environment variables:

  • PLATFORM_API_RATE_LIMIT: Per-minute, per-IP, per-instance request limit for platform APIs

@wanlingt wanlingt marked this pull request as ready for review August 8, 2023 06:13
@wanlingt wanlingt changed the title feat: platform api v1 - create and update webhook settings feat: platform api v1 - get and update webhook settings Aug 8, 2023
@@ -29,6 +29,7 @@ export const UserBase = z.object({
keyHash: z.string(),
createdAt: z.date(),
lastUsedAt: z.date().optional(),
isPlatform: z.string().optional(),
Copy link
Contributor

@tshuli tshuli Aug 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a thought: if platform users are also a kind of formsg user, will this allow platforms to modify each other's user settings in future (e.g. contact number)? I was wondering if platform tokens could be issued without creating a user account for the platform

not a super major point, just food for thought

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if platform users are also a kind of formsg user, will this allow platforms to modify each other's user settings in future (e.g. contact number)?

Yes can, if we create an endpoint which allows them to modify other users' contact number settings. We currently only have get and update webhook settings (from this PR), but we might add more endpoints in the future depending on the need. This is potentially giving them a lot of power though, so might have to think about permissions as well. I'm intentionally ignoring that right now as this is just an MVP, but recognise that this is a possible future extension!

I was wondering if platform tokens could be issued without creating a user account for the platform

And yes valid point too, worth considering hm

Copy link
Contributor

@tshuli tshuli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @wanlingt ! PR looks good with just some minor clarifications please 😃 will re-review again thereafter

#for future PR - the platform endpoint sounds like it could potentially give platforms too much power. I wonder if we need to build in additional safeguards against key loss or MITM attacks. e.g. require platform users to sign their requests, and host their signing keys on a well known endpoint for us to verify.

@wanlingt
Copy link
Contributor Author

thanks @wanlingt ! PR looks good with just some minor clarifications please 😃 will re-review again thereafter

#for future PR - the platform endpoint sounds like it could potentially give platforms too much power. I wonder if we need to build in additional safeguards against key loss or MITM attacks. e.g. require platform users to sign their requests, and host their signing keys on a well known endpoint for us to verify.

thanks for the review @tshuli , made the changes.

I think the additional safeguards is a great point. The first phase is making this available to OGP-only admins, I think we should definitely make this mechanism more secure before releasing this to WOG form admins (e.g. CPF). Might arrange a session with Eugene to better understand the safeguards we can have, will list your suggestion too

@wanlingt wanlingt requested a review from tshuli August 10, 2023 09:49
Copy link
Contributor

@tshuli tshuli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @wanlingt for addressing the comments, lgtm!

@tshuli
Copy link
Contributor

tshuli commented Aug 10, 2023

thanks @wanlingt ! PR looks good with just some minor clarifications please 😃 will re-review again thereafter
#for future PR - the platform endpoint sounds like it could potentially give platforms too much power. I wonder if we need to build in additional safeguards against key loss or MITM attacks. e.g. require platform users to sign their requests, and host their signing keys on a well known endpoint for us to verify.

thanks for the review @tshuli , made the changes.

I think the additional safeguards is a great point. The first phase is making this available to OGP-only admins, I think we should definitely make this mechanism more secure before releasing this to WOG form admins (e.g. CPF). Might arrange a session with Eugene to better understand the safeguards we can have, will list your suggestion too

Additional suggestion for future PR - perhaps you could also consider a flag to restrict platforms to managing accounts under specified domains, eg. CPFB platform account can only modify CPF forms. For OGP's platforms, they can modify any form.

@wanlingt wanlingt temporarily deployed to staging-alt August 11, 2023 06:12 — with GitHub Actions Inactive
shared/types/user.ts Outdated Show resolved Hide resolved
@wanlingt wanlingt temporarily deployed to staging August 16, 2023 04:02 — with GitHub Actions Inactive
@wanlingt wanlingt temporarily deployed to staging-alt August 16, 2023 04:47 — with GitHub Actions Inactive
@wanlingt wanlingt merged commit 753d1f2 into develop Aug 17, 2023
24 checks passed
@wanlingt wanlingt deleted the feat/platform-api-webhook branch August 17, 2023 03:02
@wanlingt wanlingt mentioned this pull request Aug 17, 2023
50 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants