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

Create Site Preview JWT in the API #2554

Merged
merged 7 commits into from
Oct 2, 2024
Merged

Conversation

fraxachun
Copy link
Contributor

@fraxachun fraxachun commented Sep 19, 2024

Allows having the Site Preview unauthenticated

Description

Before: the JWT with the preview scope and setting was generated in the site. To check if the current user is allowed to preview the given scope the site had to make a request to the API and therefore needed the access token of the current user. With this setup the site has to be behind an authproxy.

Now: the JWT is generated by the API and submitted to the site. This way the site can be public.

BREAKING

The API now requires the SITE_PREVIEW_SECRET environment variable. To make it explicit to add it this env now is also mandatory for local development.

Open TODOs/questions

  • Changeset

COM-1087

Allows having the Site Preview unauthenticated
@johnnyomair
Copy link
Collaborator

Idea to make this non-breaking: Use an existing environment variable that we know to be available in both site and API. Could be the password of the system user. For v8 we can remove this.

Alternatives:

  • Update all of our projects that are on v7 (pragmatic approach to the breaking change)
  • Use old technique if secret isn't available

@@ -748,6 +748,7 @@ type Query {
pageTreeNodeList(scope: PageTreeNodeScopeInput!, category: String): [PageTreeNode!]!
paginatedPageTreeNodes(scope: PageTreeNodeScopeInput!, category: String, sort: [PageTreeNodeSort!], documentType: String, offset: Int! = 0, limit: Int! = 25): PaginatedPageTreeNodes!
pageTreeNodeSlugAvailable(scope: PageTreeNodeScopeInput!, parentId: ID, slug: String!): SlugAvailability!
sitePreviewJwt(scope: JSONObject!, path: String!, includeInvisible: Boolean!): String!
Copy link
Member

Choose a reason for hiding this comment

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

imho this should be a mutation, not a query:

  • it creates something new (although not stored, so it strictly speaking does not mutate a database or something)
  • it should never be cached by anything, that might even result into security issues

Copy link
Member

Choose a reason for hiding this comment

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

I think so too

Copy link
Collaborator

Choose a reason for hiding this comment

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

We could call it createSitePreviewJwt or generateSitePreviewJwt

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently the request is polled (due to expiration time of jwt), this is not possible for mutations. Furthermore, useMutation does not provide refetch, which is used when changing the preview settings.

Caching however is disabled by fetchPolicy: "network-only".

Changing to a mutation requires more handwork to simulate polling and refetching. Do you still think a mutation is necessary?

Copy link
Member

Choose a reason for hiding this comment

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

Caching however is disabled

I was thinking about a future cache solution we might add

You ave good arguments, leave the query!

@nsams
Copy link
Member

nsams commented Sep 20, 2024

Allows having the Site Preview unauthenticated

👏 why didn't we do that in the first place?

@@ -66,6 +66,7 @@ NEXT_PUBLIC_API_URL=$API_URL
# site-pages
SITE_PAGES_PORT=3001
SITE_PAGES_URL=http://localhost:$SITE_PAGES_PORT
SITE_PREVIEW_SECRET=zPoURKLHPcMnV7E9
Copy link
Member

Choose a reason for hiding this comment

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

This change needs a changeset and this change should also be added to the migration guide for projects that are not on v7 yet

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changeset will be added.

I added another commit to mitigate the effort of handling the breaking change: dea0a1d

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changeset: 5d8c99a

@@ -748,6 +748,7 @@ type Query {
pageTreeNodeList(scope: PageTreeNodeScopeInput!, category: String): [PageTreeNode!]!
paginatedPageTreeNodes(scope: PageTreeNodeScopeInput!, category: String, sort: [PageTreeNodeSort!], documentType: String, offset: Int! = 0, limit: Int! = 25): PaginatedPageTreeNodes!
pageTreeNodeSlugAvailable(scope: PageTreeNodeScopeInput!, parentId: ID, slug: String!): SlugAvailability!
sitePreviewJwt(scope: JSONObject!, path: String!, includeInvisible: Boolean!): String!
Copy link
Member

Choose a reason for hiding this comment

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

I think so too

}).toString()}`;
const { data, error, refetch } = useQuery<GQLSitePreviewJwtQuery>(
gql`
query SitePreviewJwt($scope: JSONObject!, $path: String!, $includeInvisible: Boolean!) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

One downside to a mutation would be that it can't be queried like this here. But we could create it before even navigating to the site preview.

path: iframePath,
includeInvisible: showOnlyVisible ? false : true,
},
pollInterval: 1000 * 60 * 60 * 24, // due to expiration time of jwt
Copy link
Collaborator

Choose a reason for hiding this comment

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

Wouldn't this cause a location reset when a user stays too long in the site preview?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it does. Do we ignore it? (as this only happens after 24 hours)

Copy link
Collaborator

Choose a reason for hiding this comment

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

If it's 24 hours, do we even need polling?

Copy link
Contributor Author

@fraxachun fraxachun Sep 26, 2024

Choose a reason for hiding this comment

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

The expiry date of the JWT (which is stored in the site as cookie) is validated with every request. If we don't reload the SitePreview every click would result in an error. The problem occurs when a user leaves the tab opened for more than 24 hours and then continues navigation in the preview.

@nsams
Copy link
Member

nsams commented Sep 27, 2024

Regarding the breaking change:

  • we decided to accept an exceptional braking change in v7
  • should we add a comet-upgrade script that also upgrades the required deployment changes?
    • currently we don't run those for minor upgrades

@fraxachun
Copy link
Contributor Author

fraxachun commented Sep 27, 2024

  • should we add a comet-upgrade script that also upgrades the required deployment changes?

I don't think this will be necessary. After updating and startup in local dev the following error message will be shown:

BREAKING: this update of Comet v7 requires to have set sitePreviewSecret (which has to be the same value like possibly already set for site). Please refer to vivid-planet/comet-starter#371 for more information on how to upgrade.

The linked PR then shows exactly what to do.

@nsams
Copy link
Member

nsams commented Sep 27, 2024

The linked PR then shows exactly what to do.

but it doesn't show the required deployment changes

@fraxachun
Copy link
Contributor Author

but it doesn't show the required deployment changes

This is true. But it's nothing more than copying one line. We could add this to the description of the PR.

@johnnyomair
Copy link
Collaborator

johnnyomair commented Sep 30, 2024

I don't think this will be necessary. After updating and startup in local dev the following error message will be shown:

BREAKING: this update of Comet v7 requires to have set sitePreviewSecret (which has to be the same value like possibly already set for site). Please refer to vivid-planet/comet-starter#371 for more information on how to upgrade.

Wouldn't it be even better if the error message said: Please run npx @comet/upgrade v7/add-site-preview-secret.ts?

An even more crazy thought: What if the library could patch itself (i.e. include the upgrade script). I'm thinking about something like Next patches the typescript file if both Pages and App Router are used: https://github.com/vercel/next.js/blob/canary/packages/next/src/lib/typescript/writeAppTypeDeclarations.ts#L52-L56

@thomasdax98 thomasdax98 merged commit 671e2b2 into main Oct 2, 2024
11 checks passed
@thomasdax98 thomasdax98 deleted the site-preview-not-authproxy branch October 2, 2024 14:46
@johnnyomair johnnyomair mentioned this pull request Oct 3, 2024
fraxachun added a commit to vivid-planet/comet-upgrade that referenced this pull request Oct 4, 2024
johnnyomair pushed a commit to vivid-planet/comet-upgrade that referenced this pull request Oct 7, 2024
dkarnutsch added a commit to vivid-planet/comet-starter that referenced this pull request Oct 15, 2024
<!--

PLEASE MAKE SURE TO KEEP THE PR SIZE AT A MINIMUM!
Smaller PRs are easier to review and tend to get merged faster.
Unrelated changes, refactorings, fixes etc. should be made in separate
PRs.

--->

## Description

Add deployment based on [DigitalOcean's app
platform](https://www.digitalocean.com/products/app-platform). The apps
are split per domain to be compatible with routing from the app
platform.

The preview does not work yet, as I'm waiting for
vivid-planet/comet#2554.

I decided to not commit the symlinks and copy the files instead to keep
the required changes minimal.

The secrets are
[safe](https://docs.digitalocean.com/products/app-platform/how-to/use-environment-variables/)
inside the repo as they are encrypted.

This does not include a secondary site, but could be added later.

<!--

The description should describe the change you're making.
It will be used as the commit message for the squashed commit once the
PR gets merged.
Therefore, make sure to keep the description up-to-date as the PR
changes.

PLEASE DESCRIBE WHY YOU'RE MAKING THE CHANGE, NOT WHAT YOU'RE CHANGING.
Reviewers see what you're changing when reviewing the code.
However, they might not understand your motives as to why you're making
the change.

Your description should include:
-   The problem you're facing
-   Your solution to the problem
-   An example usage of your change

--->

<!--

Everything below this is intended to help ease reviewing this PR.
Remove all unrelated sections.

WHEN MERGING THE PR, REMOVE THIS FROM THE COMMIT MESSAGE.

-->

## Screenshots/screencasts

<!--

When making a visual change, please provide either screenshots or
screencasts.

Hint: For before/after views, you can use a table:

| Before   | After   |
| -------- | ------- |
| Link     | Link    |

-->

## Related tasks and documents

<!--

Link to related tasks and documents, for instance,
https://vivid-planet.atlassian.net/browse/COM-XXX.

MAKE SURE THAT EVERYTHING REQUIRED TO UNDERSTAND YOUR CHANGE IS IN THE
PR DESCRIPTION.
Reviewers shouldn't need to review tasks, JIRA conversations etc. to
understand what you're doing.

-->

## Open TODOs/questions (Future PR)

- [ ] Remove dependency to dkarnutsch/oauth2-proxy (no really
trustworthy image from Docker Hub found and GitHub registry does not
work yet on DigitalOcean)
- [ ] Replace domains with starter.comet-dxp.com and
admin.starter.comet-dxp.com
-   [ ] Add CI/CD based on GitHub Actions


## Further information

<!--

Further information that helps reviewing the PR, for instance:
-   Alternative solutions you have considered
-   Dependent PRs
-   Links to relevant documentation, blog posts etc.

-->
fraxachun added a commit that referenced this pull request Oct 21, 2024
Since #2554 the
site preview isn't anymore behind an authproxy. As a
consequence preview urls do not work anymore, but creating
normal hashed urls should be sufficient
fichtnerma pushed a commit that referenced this pull request Nov 3, 2024
Allows having the Site Preview unauthenticated

## Description

Before: the JWT with the preview scope and setting was generated in the
site. To check if the current user is allowed to preview the given scope
the site had to make a request to the API and therefore needed the
access token of the current user. With this setup the site has to be
behind an authproxy.

Now: the JWT is generated by the API and submitted to the site. This way
the site can be public.

## BREAKING
The API now requires the SITE_PREVIEW_SECRET environment variable. To
make it explicit to add it this env now is also mandatory for local
development.
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.

4 participants