Some types and fields can contain data that is specific to a certain user. Cached query results that contain those types (or fields) should not be returned to any other user.

In order to handle this scenario, you can define "scopes" in your service which let you scope (hence the name) cached query results to specific headers and/or cookies.

Every service has a special PUBLIC scope it uses by default. This scope returns the same cached results for all users.

Basics

You can define scopes for your service based on the header and/or cookie your users use to authenticate. For simplicity's sake, we are going to show examples using the configuration file, however, you can define scopes via the UI as well.

scopes: 
  AUTHORIZATION_HEADER: 'header:Authorization'
  SESSION_COOKIE: 'cookie:session'

Unless you are certain you want to cache them separately, combine all your authentication methods into a single scope with a pipe (|, which means "or") to avoid having to create excessive rules.

scopes: 
  AUTHENTICATED: 'header:Authorization|cookie:session'

🚧

Header names are case-insensitive, cookie names are case-sensitive.

Using scopes

To set the scope a certain query result should be cached by, create a cache rule for the types you want to cache separately per-user (see Cache Rules for more information):

rules: 
  - description: 'Cache any user-specific data per-user'
    types: 
      User: true
    scope: AUTHENTICATED 

Now any query result that contains any User will be cached with the corresponding cookie and/or header of the AUTHENTICATED scope and will only be returned for the same requester. Users that aren't authenticated will still get the same cached results.

JWT Based Scopes

📘

Beta feature

JWT based scopes are currently in Beta and can only be configured via the configuration file. There are some limitations with this feature, as mentioned further down on this page. If you want to use JWT based scopes, make sure you are using CLI version 1.9.2 or later.

If you have questions regarding this feature, feel free to reach out via the in-app messenger, or email us at [email protected].

scopes:
  # To support JWT scopes we modified our config format so that you may
  # pass `definition` and the optional `jwt` option separately.
  AUTHENTICATED:
    definition: header:authorization
    # Setting this marks the scope as "the value of the definition contains 
    # a JWT". If you pass multiple headers and/or cookies in the definition,
    # we'll take the first existing value we can find.
    jwt:
      # Pass the claim by which the cache should be scoped
      claim: sub
      # Pass the algorithm you use to sign your JWTs
      algorithm: HS256
      # Pass the secret you use for signing (or the public key when using
      # an asymmetric algorithm)
      # secret: very_secret_passphrase
      secret: |
        -----BEGIN PUBLIC KEY-----
        MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo
        4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u
        +qKhbwKfBstIs+bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyeh
        kd3qqGElvW/VDL5AaWTg0nLVkjRo9z+40RQzuVaE8AkAFmxZzow3x+VJYKdjykkJ
        0iT9wCS0DRTXu269V264Vf/3jvredZiKRkgwlL9xNAwxXFg0x/XFw005UWVRIkdg
        cKWTjpBP2dPwVZ4WWC+9aGVd+Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbc
        mwIDAQAB
        -----END PUBLIC KEY-----

  # Sidenote: The shorthand for passing just a string here still works!
  ANOTHER_SCOPE: cookie:session
  • We support nested claims using lodash-like dotpath-notation, e.g. by passing user.id to claim.
  • Supported algorithms are: HS256, HS384, and HS512 (symmetric), RS256, RS384, and RS512 (asymmetric), ES256 (asymmetric) as well as PS256, PS384, and PS512 (asymmetric)
  • When using an asymmetric signature, the public key shall be passed as value for secret as shown in the example above.

Limitations with JWT based scopes

  • JWT based scopes can NOT be configured via the dashboard at this time. The scope will be displayed on the dashboard, however, without the JWT specific configuration.
  • After pushing the config it takes some time for the changes to actually come into effect globally. This can vary between a couple of seconds and 1-2 minutes. We’re looking into how we can make this faster and/or predictably wait when pushing until the propagation of these changes is complete.
  • The combined size of all secrets / public keys used in JWT scopes must not exceed 6,000 characters.
  • We do not support JSON Web Key Sets (JWKS) at this time. Your configuration will need to refer to the actual public key and not a JWKS URL at this time.
  • If your claim includes dots like e.g. Hasura does with their default configuration, you will need to escape those dots with a backslash, e.g. to cache based on the user ID for the example configuration shared at https://hasura.io/docs/latest/graphql/core/auth/authentication/jwt/#the-spec
scopes:
  AUTHENTICATED:
    definition: header:authorization
      jwt:
        claim: https://hasura\.io/jwt/claims.x-hasura-user-id

Did this page help you?