Skip to content

Conversation

@rkistner
Copy link
Contributor

@rkistner rkistner commented Jul 4, 2024

Adds new functions, for use in parameter queries only:

  1. request.jwt(): Returns the entire (signed) JWT payload as a JSON string.
  2. request.parameters(): Returns the client parameters (unauthenticated) as a JSON string.
  3. request.user_id(): Returns the token subject, same as token_parameters.user_id().

These are similar to the current token_parameters and user_parameters (added in #7) respectively. The major differences are that the entire payloads are preserved as-is, which can make usage a little more intuitive. It also includes JWT payload fields not previously accessible.

Examples:

request.jwt() ->> 'sub' -- Same as token_parameters.user_id. Makes it clear which JWT field is used.
request.user_id() -- Same as `request.jwt() ->> 'sub'` and `token_parameters.user_id`
request.parameters() ->> 'param' -- Similar to as user_parameters.param.

-- Some supabase-specific examples below. These can be used with standard Supabase tokens, for use cases which previously required custom tokens
request.jwt() ->> 'role' -- 'authenticated' or 'anonymous'
request.jwt() ->> 'email' -- automatic email field
request.jwt() ->> 'user_metadata.custom_field' -- custom field added on the client (not authenticated)
request.jwt() ->> 'app_metadata.custom_field' -- custom field added by a service account (authenticated)

-- Complete examples:

-- Sync archived projects only when specifically requested in client parameters, authenticated by org_id
SELECT id as project_id FROM projects WHERE org_id IN request.jwt() ->> 'app_metadata.org_id' AND archived = true AND request.parameters() ->> 'include_archived'

-- Only sync selected projects, authenticated by org_id
SELECT id as project_id FROM projects WHERE org_id IN request.jwt() ->> 'app_metadata.org_id' AND id IN request.parameters() -> 'selected_projects'

Implementation

This builds on the refactor in #30.

The biggest change here is to make static parameter queries behave the same as other parameter queries. Previously, static parameter queries treated token_parameters and user_parameters as row data, while other queries treated it as parameter data. Now, both treat it as parameter data.

From there it's just implementing two special-case functions as ParameterValueClauses.

SyncParameters was also refactored to get access to the raw payloads in sync rules.

Naming things

  • Should the jwt function be request.jwt() to match request.parameters(), or auth.jwt() to match Supabase RLS?
  • Should we add request.user_id(), or auth.uid() to match Supabase RLS?
  • Should we make it more explicit that parameters are not authenticated, e.g. request.unauthenticated_parameters()?

Warning on potentially dangerous queries

To identify potentially dangerous queries, this checks for queries that:

  1. Use request.parameters() (or user_parameters).
  2. Does not use request.jwt() (or token_parameters).

There are some special cases deviating from those, but that's the general principle. These warnings can be disabled by specifying accept_potentially_dangerous_queries: true in the bucket definition.

Message updated since screenshot:

Potentially dangerous query based on parameters set by the client. The client can send any value for these parameters so it's not a good place to do authorization.

image

Accepting the warning:
image

Function documentation

This adds basic documentation for each function definition, for use in the sync rules editor.

image

rkistner added 7 commits July 4, 2024 15:06
They are now more consistent with standard parameter queries.
This adds support for request.parameters() in static parameter queries.
This now matches the rest of parameter query handling.
This adds support for request.parameters() in select clause of parameter
queries.
This adds the raw JWT payload to the request parameters, and moves
some normalization logic from the auth function to sync rules.
@changeset-bot
Copy link

changeset-bot bot commented Jul 4, 2024

🦋 Changeset detected

Latest commit: e0200a3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@powersync/service-sync-rules Minor
@powersync/service-core Minor
powersync-open-service Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rkistner rkistner requested a review from Chriztiaan July 4, 2024 14:13
@Chriztiaan
Copy link
Contributor

Good so far.

Chriztiaan
Chriztiaan previously approved these changes Jul 8, 2024
Chriztiaan
Chriztiaan previously approved these changes Jul 8, 2024
@rkistner rkistner marked this pull request as ready for review July 8, 2024 17:20
Chriztiaan
Chriztiaan previously approved these changes Jul 9, 2024
@rkistner rkistner merged commit 28f4aca into main Jul 9, 2024
@rkistner rkistner deleted the request-parameters branch July 9, 2024 14:20
@rkistner rkistner changed the title Support for request.parameters() Support for request.parameters(), request.jwt() and request.user_id() Jul 9, 2024
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