Skip to content

Commit

Permalink
fix!: migrated from cookieyes to a custom cookie solution
Browse files Browse the repository at this point in the history
Co-authored-by: meza <[email protected]>
Co-authored-by: SJ Hayman <[email protected]>
  • Loading branch information
3 people authored Apr 2, 2023
1 parent 8701777 commit 36115e2
Show file tree
Hide file tree
Showing 76 changed files with 2,840 additions and 323 deletions.
4 changes: 3 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ module.exports = {
'@typescript-eslint/ban-ts-comment': 'off',
'no-use-before-define': 'off',
'max-nested-callbacks': 'off',
'sonarjs/no-duplicate-string': 'off'
'sonarjs/no-duplicate-string': 'off',
'sonarjs/no-identical-functions': 'off'
}
}
],
Expand Down Expand Up @@ -81,6 +82,7 @@ module.exports = {
pathGroupsExcludedImportTypes: ['type']
}
],
'jsx-quotes': [ 'error', 'prefer-single' ],
'sonarjs/no-duplicate-string': 'off',
'no-continue': 'off',
'dot-notation': 'error',
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
with:
command: install
node-version: "19.7.0"
node-version: "latest"
junit-report-path: "reports/junit.xml"
cobertura-report-path: "reports/**/cobertura-coverage.xml"
build:
Expand All @@ -29,7 +29,7 @@ jobs:
uses: meza/action-setup-node-npm@main
with:
command: install
node-version: 19.7.0
node-version: latest
cache-name: ${{ needs.verify.outputs.cache-name }}
- name: 🔂 CDK Cache
uses: pat-s/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ephemeralDeploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
uses: meza/action-setup-node-npm@main
with:
command: install
node-version: 19.7.0
node-version: latest
cache-name: ${{ needs.verify.outputs.cache-name }}
- name: 🔂 CDK Cache
uses: actions/cache@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ephemeralDestroy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
uses: meza/action-setup-node-npm@main
with:
command: install
node-version: 19.7.0
node-version: latest
cache-name: destroy-${{ github.event.ref }}
- name: 🔨 Build
run: npm run build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
uses: meza/action-setup-node-npm@main
with:
command: install
node-version: 19.7.0
node-version: latest
cache-name: 'playwright'
- name: Create envfile
uses: SpicyPizza/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/storybook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
uses: meza/action-setup-node-npm@main
with:
command: install
node-version: 19.7.0
node-version: latest
cache-name: storybook
- name: Build Storybook
run: npm run storybook:build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ jobs:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
with:
command: install
node-version: "19.7.0"
node-version: "latest"
junit-report-path: "reports/junit.xml"
cobertura-report-path: "reports/**/cobertura-coverage.xml"
22 changes: 5 additions & 17 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,21 @@
import i18n from '../testUtils/i18nextForStorybook';
import React, { useEffect } from 'react';
import { ColorMode, ColorModeContext } from '~/components/ColorModeSwitcher';
import { StoryContext, StoryFn } from '@storybook/react';
import { StoryFn } from '@storybook/react';
import '../src/styles/app.css';
import './storybook.css';
import { I18nextProvider } from 'react-i18next';
import theme from './theme';
import { useGlobals } from '@storybook/addons';
import { useGlobals } from '@storybook/preview-api';
import { createRemixStub } from '@remix-run/testing/dist/create-remix-stub';

const createRemixStoryDecorator = (Story: StoryFn) => {
const RemixStub = createRemixStub([
{
path: '/*',
element: <Story/>,
action: () => ({ redirect: '/' }),
loader: () => ({ redirect: '/' })
}
]);
return <RemixStub/>;
};

const withAllTheThings = (Story: StoryFn, context: StoryContext) => {
const withAllTheThings = (Story: StoryFn) => {
const [globals, updateGlobals] = useGlobals();
const colorMode = globals.colorMode || ColorMode.LIGHT;

const setStoryColorMode = (mode: ColorMode, force = true) => {

const cl = document.firstElementChild?.classList;
document.firstElementChild.classList.remove(ColorMode.LIGHT, ColorMode.DARK);
document.firstElementChild?.classList.remove(ColorMode.LIGHT, ColorMode.DARK);
if (cl) {
cl.remove(ColorMode.LIGHT, ColorMode.DARK);
cl.add(mode);
Expand Down
1 change: 0 additions & 1 deletion .storybook/storybook.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@
.storybook-canvas {
background-color: var(--color-secondary) !important;
color: var(--color-primary) !important;
@custom-media --motion-ok true;
}
99 changes: 69 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ You can modify it to your liking and use it as a base for your own remix project
- [Auth0](https://auth0.com/) for authentication
- [Split](https://split.io) for feature flags
- [Sentry](https://sentry.io) for Client Side error tracking (server side soon)
- [CookieYes](https://cookieyes.com) for cookie consent
- Custom-built cookie consent banner to maximise security [read more](./docs/adr/0013-custom-cookie-consent.md)
- Analytics Integrations
- [Mixpanel](https://mixpanel.com)
- [Hotjar](https://hotjar.com)
Expand Down Expand Up @@ -129,8 +129,6 @@ npm run dev
* [Adding the Auth0 variables to GitHub](#adding-the-auth0-variables-to-github)
* [Enabling the Auth0 integration for feature branch/PR deployments](#enabling-the-auth0-integration-for-feature-branchpr-deployments)
* [Removing the Auth0 integration from the application](#removing-the-auth0-integration-from-the-application)
* [CookieYes integration](#cookieyes-integration)
* [Removing the CookieYes integration from the application](#removing-the-cookieyes-integration-from-the-application)
* [Google Analytics 4 integration](#google-analytics-4-integration)
* [Removing the Google Analytics 4 integration from the application](#removing-the-google-analytics-4-integration-from-the-application)
* [Hotjar integration](#hotjar-integration)
Expand All @@ -149,6 +147,8 @@ npm run dev
* [Branching Strategy with Semantic Versioning](#branching-strategy-with-semantic-versioning)
* [Linting](#linting)
* [Which version am I running?](#which-version-am-i-running)
* [Cookie Consent](#cookie-consent)
* [Using the consent provider](#using-the-consent-provider)
* [Dependency Version Updates](#dependency-version-updates)
* [Runtime dependencies](#runtime-dependencies)
* [Development dependencies](#development-dependencies)
Expand Down Expand Up @@ -410,33 +410,6 @@ http://localhost:3000/auth/callback,https://*.execute-api.us-east-1.amazonaws.co
3. Delete the `auth0-remix-server` dependency from the `package.json` file.
4. Follow the compilation and test errors to remove all the code that uses the `auth0-remix-server` dependency.

### CookieYes integration

We use [CookieYes](https://www.cookieyes.com) for cookie consent. You will need to create an account with them and
[set up a cookie banner](https://www.cookieyes.com/category/documentation/getting-started/).

When you are prompted with installation instructions or navigate to https://app.cookieyes.com/site-settings, you will
need
to copy the code following the `client_data/` in the script src and paste it in the `.env` file:

<p align="center">
<img src="./docs/images/cookieyes.png" alt="CookieYes Instructions" />
</p>

You will also have to go to the [variables settings][gh-variables] and add the same variable
name as the one in the `.env` file.

> **Warning**
> The `COOKIEYES_TOKEN` is **set as a variable** for the actions.
#### Removing the CookieYes integration from the application

1. Delete the `COOKIEYES_TOKEN` variable from the `.env` file and GitHub variables.
2. Delete the `src/components/Cookieyes` directory.
3. Delete the relevant types off the `appConfig` type in the `src/types/global.d.ts` file.
4. Delete the `<Cookieyes ... />` component and its import from the `src/root.tsx` file.
5. Run `vitest --run --update` to update the snapshots.

### Google Analytics 4 integration

We use [Google Analytics v4](https://analytics.google.com) for analytics. You will need to create an account with them
Expand Down Expand Up @@ -740,6 +713,72 @@ The version of the app is sent into the `<html data-version="...">` attribute. Y
version
of the app is running on any given environment.

### Cookie Consent

We have built a custom cookie consent solution that is compatible with secure XSS protection practices as well as with
the EU cookie law.

> **Note**
> you can read more about this in the [Cookie Consent ADR](./docs/adr/0001-cookie-consent.md)
The solution is in the `src/components/CookieConsent` folder, and **it is meant to be modified to fit your needs.**

When you open up the `index.tsx` file there, you can see the following interfaces:

```ts
interface ConsentData {
analytics?: boolean | undefined;
//add your own if you need more
// marketing?: boolean | undefined;
// tracking?: boolean | undefined;
}

interface CookieConsentContextProps {
analytics?: boolean | undefined;
setAnalytics: (enabled: boolean) => void;
//add your own if you need more
// marketing?: boolean | undefined;
// setMarketing: (enabled: boolean) => void;
// tracking?: boolean | undefined;
// setTracking: (enabled: boolean) => void;
}
```

You will need to modify these in order to add your specific cookie types. For example, if you want to add a `marketing`
cookie, you will need to add the following:

```ts
interface ConsentData {
analytics?: boolean | undefined;
marketing?: boolean | undefined;
}

interface CookieConsentContextProps {
analytics?: boolean | undefined;
setAnalytics: (enabled: boolean) => void;
marketing?: boolean | undefined;
setMarketing: (enabled: boolean) => void;
}
```

#### Using the consent provider

In order to adhere to the cookie consent, you will need to identify the elements of your project that add a specific
type of cookie.

> A good example in this stack is the GoogleAnalytics component. It is located in the `src/components/GoogleAnalytics`
The cookie consent provider is use in the `root.tsx` file, so it's available for all your components.
To use it, all you need to do is:

```tsx
const { analytics } = useContext(CookieConsentContext);

if (analytics) {
//add your analytics code here
}
```

### Dependency Version Updates

We use [Renovate](https://www.mend.io/free-developer-tools/renovate) to automatically update the dependencies.
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/.adr-sequence.lock
Original file line number Diff line number Diff line change
@@ -1 +1 @@
11
13
25 changes: 25 additions & 0 deletions docs/adr/0012-session-cookie-same-site-none.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# 12. Session Cookie Same Site None

Date: 2023-03-25

## Status

Accepted

## Context

We've fought long and hard to keep the session cookie same-site: lax at the minimum however we've been running into a lot
of issues.

Mainly that during the authorization process, the cookie wouldn't be sent back to us when auth0 makes a POST request to the
callback URL.

This meant that the cookie consent, the theme setting and the visitor ID all got wiped out and forgotten.

## Decision

The decision is to use the SameSite: None setting, like most of the internet does.

## Consequences

While this doesn't pose too much of an added security risk, it's still not as secure as it could be.
51 changes: 51 additions & 0 deletions docs/adr/0013-custom-cookie-consent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# 13. Custom Cookie Consent

Date: 2023-04-02

## Status

Accepted

## Context

The cookie laws in the EU are rather strict and require that users are informed about the cookies that are being used on
a website and that they have the ability to opt out of cookies that are not necessary for the website to function.

One of the main specifics of this is that cookies **cannot be stored** until the user has given their consent.

It is common practice to use third party providers for the consent management.

We've explored the use of:

- [Cookiebot](https://www.cookiebot.com/en/)
- [CookieYes](https://www.cookieyes.com/)
- [OneTrust](https://www.onetrust.com/)

... and a few more.

What we've discovered is that the way these providers work is by injecting a script into the page which then intercepts
all the subsequent <script> tags and replaces them with a script that will only be executed if the user has given consent.

This is a problem when you're aiming to also have a high level of XSS protection in place.

These scripts will remove the script tags and then inject them back into the page, which means that the browser will block
the script from executing.

This is a general problem across the board with all of these providers.

## Decision

In order to have both a secure solution and a solution that is compliant with the EU cookie laws, we've decided to build
our own solution.

## Consequences

Due to this, there is a bit more maintenance involved in keeping the solution up to date.

- We need to hand-craft the cookie policies that list out the cookies we use and what they are used for.
- We need to keep the cookie policies up to date with any changes to the cookies we use.

The other unfortunate consequence / trade-off is that when the user does give consent, we *must* perform a page
reload in order to inject the scripts that were blocked by the browser.

It's a small price to pay for the security and compliance.
3 changes: 2 additions & 1 deletion docs/adr/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
- [9. No more need to bundle environment variables](0009-no-more-need-to-bundle-environment-variables.md)
- [10. Auth by Auth0](0010-authentication-is-done-by-auth0.md)
- [11. Suppressing Hydration Warnings on Scripts](0011-suppressing-hydration-warnings-on-scripts.md)
- [12. Suppressing Hydration Warnings on Scripts](0012-suppressing-hydration-warnings-on-scripts.md)
- [12. Session Cookie Same Site None](0012-session-cookie-same-site-none.md)
- [13. Custom Cookie Consent](0013-custom-cookie-consent.md)
Loading

0 comments on commit 36115e2

Please sign in to comment.