From 890709f7e1d4e33f960fa128537689f55556eb51 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Sat, 25 Jan 2020 14:31:04 +0100 Subject: [PATCH] feat: Authenticate all backend calls with Hawk (#411) * Add Hawk * Make hawk work * Put back staging * Update readme * Reput old slug * Remove unused dep * Pre-fill hawk key for staging * Update README --- .github/workflows/pr.yml | 4 +- .gitignore | 1 + App/ambient.d.ts | 1 + App/stores/util/createHistoryItem.ts | 2 +- .../{createUser.ts => getOrCreateUser.ts} | 0 App/stores/util/index.ts | 2 +- App/stores/util/updateUser.ts | 2 +- App/util/apollo.ts | 18 ++++++ README.md | 17 +++--- app.example.json | 1 + package.json | 1 + yarn.lock | 60 +++++++++++++++++++ 12 files changed, 96 insertions(+), 13 deletions(-) rename App/stores/util/{createUser.ts => getOrCreateUser.ts} (100%) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index ea51c303..486a9c4a 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - - name: Lint + - name: Run yarn lint run: | yarn install yarn lint @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - - name: Test + - name: Run yarn test run: | yarn install yarn test diff --git a/.gitignore b/.gitignore index e3eb07a4..f213200c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ yarn-error.log* # secrets app.json +app.prod.json # ide files .idea/ diff --git a/App/ambient.d.ts b/App/ambient.d.ts index e252c3e0..5ad97c7a 100644 --- a/App/ambient.d.ts +++ b/App/ambient.d.ts @@ -17,3 +17,4 @@ declare module '*.json'; declare module '*.mp4'; declare module '*.png'; +declare module '@hapi/hawk/lib/browser'; diff --git a/App/stores/util/createHistoryItem.ts b/App/stores/util/createHistoryItem.ts index 575f5170..9db36709 100644 --- a/App/stores/util/createHistoryItem.ts +++ b/App/stores/util/createHistoryItem.ts @@ -24,7 +24,7 @@ import * as TE from 'fp-ts/lib/TaskEither'; import { client } from '../../util/apollo'; import { promiseToTE, sideEffect } from '../../util/fp'; import { Api } from '../api'; -import { getOrCreateUser } from './createUser'; +import { getOrCreateUser } from './getOrCreateUser'; const CREATE_HISTORY_ITEM = gql` mutation createHistoryItem($input: CreateHistoryItemInput!) { diff --git a/App/stores/util/createUser.ts b/App/stores/util/getOrCreateUser.ts similarity index 100% rename from App/stores/util/createUser.ts rename to App/stores/util/getOrCreateUser.ts diff --git a/App/stores/util/index.ts b/App/stores/util/index.ts index 02e34f9e..1bc86260 100644 --- a/App/stores/util/index.ts +++ b/App/stores/util/index.ts @@ -15,5 +15,5 @@ // along with Sh**t! I Smoke. If not, see . export * from './createHistoryItem'; -export * from './createUser'; export * from './fetchGpsPosition'; +export * from './getOrCreateUser'; diff --git a/App/stores/util/updateUser.ts b/App/stores/util/updateUser.ts index 566c805c..e893601b 100644 --- a/App/stores/util/updateUser.ts +++ b/App/stores/util/updateUser.ts @@ -22,7 +22,7 @@ import * as TE from 'fp-ts/lib/TaskEither'; import { client } from '../../util/apollo'; import { promiseToTE, sideEffect } from '../../util/fp'; -import { getOrCreateUser } from './createUser'; +import { getOrCreateUser } from './getOrCreateUser'; const UPDATE_USER = gql` mutation updateUser($userId: ID!, $input: UpdateUserInput!) { diff --git a/App/util/apollo.ts b/App/util/apollo.ts index ebbddbc0..da353e02 100644 --- a/App/util/apollo.ts +++ b/App/util/apollo.ts @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Sh**t! I Smoke. If not, see . +import Hawk from '@hapi/hawk/lib/browser'; import { historyItemSchema, measurementSchema, @@ -28,10 +29,27 @@ const BACKEND_URI = ? 'https://shootismoke.now.sh/api/graphql' : 'https://staging.shootismoke.now.sh/api/graphql'; +const credentials = { + id: `${Constants.manifest.slug}-${Constants.manifest.releaseChannel || + 'development'}`, + key: Constants.manifest.extra.hawkKey, + algorithm: 'sha256' +}; + /** * The Apollo client */ export const client = new ApolloClient({ + request: (operation): void => { + // Set Hawk authorization header on each request + const { header } = Hawk.client.header(BACKEND_URI, 'POST', { credentials }); + + operation.setContext({ + headers: { + authorization: header + } + }); + }, typeDefs: [historyItemSchema, measurementSchema, userSchema], uri: BACKEND_URI }); diff --git a/README.md b/README.md index d0753293..a24c9434 100644 --- a/README.md +++ b/README.md @@ -42,14 +42,15 @@ This app is bootstrapped with [Expo](https://expo.io), you can download the Expo Before developing the app, you need to fetch your own API tokens for the following services: -| Service | Url | Comments | -| ----------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -| World Air Quality Index | http://aqicn.org/api/ | Required. You can use the dummy one in `app.example.json` for development. | -| Algolia Places | https://community.algolia.com/places/ (`Get Started` button on the bottom) | Optional, lower API rates if not provided. | -| Google Maps for iOS | https://developers.google.com/maps/documentation/ios-sdk/start | Optional in development. | -| Google Maps for Android | https://developers.google.com/maps/documentation/android-api/ | Optional in development. | -| Sentry Bug Tracking | https://sentry.io | Optional. | -| Amplitude Analytics | https://amplitude.com | Optional. Note: we **never** track PII. | +| Service | Url | Comments | +| ------------------------ | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | +| Sh\*\*t! I Smoke Backend | https://github.com/shootismoke/backend | Required. Pre-filled with a staging token. | +| World Air Quality Index | http://aqicn.org/api/ | Required. You can use the dummy one in `app.example.json` for development. | +| Algolia Places | https://community.algolia.com/places/ (`Get Started` button on the bottom) | Optional, lower API rates if not provided. | +| Google Maps for iOS | https://developers.google.com/maps/documentation/ios-sdk/start | Optional in development. | +| Google Maps for Android | https://developers.google.com/maps/documentation/android-api/ | Optional in development. | +| Sentry Bug Tracking | https://sentry.io | Optional. | +| Amplitude Analytics | https://amplitude.com | Optional. Note: we **never** track PII. | Then run the following commands: diff --git a/app.example.json b/app.example.json index df2de66a..c23fa682 100644 --- a/app.example.json +++ b/app.example.json @@ -17,6 +17,7 @@ "algoliaApplicationId": null, "aqicnToken": "6bb4237574756ba29f05cea553bd22576596c11e", "amplitudeApiKey": null, + "hawkKey": "26bb8794-8f1e-4bf7-b977-081186af58d6", "sentryPublicDsn": null }, "githubUrl": "https://github.com/amaurymartiny/shoot-i-smoke", diff --git a/package.json b/package.json index b3c7c45b..01a3bf28 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "dependencies": { "@apollo/react-hooks": "^3.1.3", "@expo/vector-icons": "^10.0.0", + "@hapi/hawk": "^8.0.0", "@shootismoke/convert": "^0.2.6", "@shootismoke/dataproviders": "^0.2.6", "@shootismoke/graphql": "^0.2.6", diff --git a/yarn.lock b/yarn.lock index 87651546..e37bb8fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1352,16 +1352,61 @@ resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" integrity sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ== +"@hapi/b64@5.x.x": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@hapi/b64/-/b64-5.0.0.tgz#b8210cbd72f4774985e78569b77e97498d24277d" + integrity sha512-ngu0tSEmrezoiIaNGG6rRvKOUkUuDdf4XTPnONHGYfSGRmDqPZX5oJL6HAdKTo1UQHECbdB4OzhWrfgVppjHUw== + dependencies: + "@hapi/hoek" "9.x.x" + +"@hapi/boom@9.x.x": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-9.0.0.tgz#28f9e77ecf2dea1fe3a8982b9d8827aa5137e33a" + integrity sha512-D+Or4yahLq3L7D1Jf0fR1+Lgr+HPK1lej8tc6hS/fBLmK66XdpvTyKv8YUR5ls1GeQy+KGtbpKAs+ZxyzNtUyA== + dependencies: + "@hapi/hoek" "9.x.x" + +"@hapi/bounce@2.x.x": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@hapi/bounce/-/bounce-2.0.0.tgz#e6ef56991c366b1e2738b2cd83b01354d938cf3d" + integrity sha512-JesW92uyzOOyuzJKjoLHM1ThiOvHPOLDHw01YV8yh5nCso7sDwJho1h0Ad2N+E62bZyz46TG3xhAi/78Gsct6A== + dependencies: + "@hapi/boom" "9.x.x" + "@hapi/hoek" "9.x.x" + "@hapi/bourne@1.x.x": version "1.3.2" resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-1.3.2.tgz#0a7095adea067243ce3283e1b56b8a8f453b242a" integrity sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA== +"@hapi/cryptiles@5.x.x": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@hapi/cryptiles/-/cryptiles-5.0.0.tgz#364ca3336594c7f261707a527c4d36da4a8eb86e" + integrity sha512-Yq43ti9N51Z7jbm0Q7YVCcofA+4Gh5wsBX/jZ++Z+FM8GYfBQ1WmI9ufZSL+BVX8vRxzDkdQ2fKoG6cxOQlnVQ== + dependencies: + "@hapi/boom" "9.x.x" + +"@hapi/hawk@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@hapi/hawk/-/hawk-8.0.0.tgz#2e45c8f9992cd9d96b56346c1aac7186fac3a723" + integrity sha512-VEvZUMfZKjXadT9XUt5543ol2DJN7cbcz0j/03wzVcuFxyjuyUaM38aHjf4jxr4feU9B2RT9JOV+H9Q4Ax72qA== + dependencies: + "@hapi/b64" "5.x.x" + "@hapi/boom" "9.x.x" + "@hapi/cryptiles" "5.x.x" + "@hapi/hoek" "9.x.x" + "@hapi/sntp" "4.x.x" + "@hapi/hoek@8.x.x", "@hapi/hoek@^8.3.0": version "8.5.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.0.tgz#2f9ce301c8898e1c3248b0a8564696b24d1a9a5a" integrity sha512-7XYT10CZfPsH7j9F1Jmg1+d0ezOux2oM2GfArAzLwWe4mE2Dr3hVjsAL6+TFY49RRJlCdJDMw3nJsLFroTc8Kw== +"@hapi/hoek@9.x.x": + version "9.0.2" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.0.2.tgz#57597083f763eafbfdc902d16ec868aa787b24d2" + integrity sha512-LyibKv2QnD9BPI5g2L+g85yiIPv3ajYpENGFgy4u0xCLPhXWG1Zdx29neSB8sgX0/wz6k5TMjHzTwJ6+DaBYOA== + "@hapi/joi@^15.0.3": version "15.1.1" resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7" @@ -1372,6 +1417,21 @@ "@hapi/hoek" "8.x.x" "@hapi/topo" "3.x.x" +"@hapi/sntp@4.x.x": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@hapi/sntp/-/sntp-4.0.0.tgz#2095bfd7bbe0e6cf0eced55a7598035815b8e02e" + integrity sha512-yBXTlySZyPZKz0NPoxxFClKNMmVhsZq84Ir7+k93XNGLdSnY3iD0BosxflLpIbP7yr3p4T+QDPMNgOA3XccdFQ== + dependencies: + "@hapi/boom" "9.x.x" + "@hapi/bounce" "2.x.x" + "@hapi/hoek" "9.x.x" + "@hapi/teamwork" "4.x.x" + +"@hapi/teamwork@4.x.x": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@hapi/teamwork/-/teamwork-4.0.0.tgz#4aadbb88de13bce39ab8431565cd50c7ecc6327f" + integrity sha512-V6xYOrr5aFv/IJqNPneaYCu8vuGTKisamqHVRS3JJnbZr18TrpXdsJOYk9pjPhFti+M2YETPebQLUr820N5NoQ== + "@hapi/topo@3.x.x": version "3.1.6" resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.6.tgz#68d935fa3eae7fdd5ab0d7f953f3205d8b2bfc29"