@remkoj/optimizely-graph-client
TypeScript icon, indicating that this package has built-in type declarations

3.2.0 • Public • Published

Optimizely Graph Client

An extension of the graphql-request package, providing the configuration and additional logic needed to connect with Optimizely Graph.

Within this document

1. Provided services

The package contains the following services:

  • The configuration logic, to read and validate the configuration. Supports both runtime configuration objects as well a reading from environment variables.
  • The GraphQL Client, based upon graphql-request, supporting the following authentication schemes for Optimizely Graph:
    • Public access (e.g. using the Single key)
    • HMAC Signed messages
    • Basic Authentication
    • Token pass-through (for Optimizely CMS in context editing)
  • A RouteResolver, which simplifies handling routes when using Optimizely CMS, using the Optimizely Graph as datasource.
  • A ChannelRepository, which simplifies reading channel (website) configuration from the Optimizely CMS, using the Optimizely Graph as datasource.
  • An OpenAPI Client for the administrative REST services of Optimizely Graph. This follows the service specification and is based upon the code generated by openapi-typescript-codegen from this service specification.

2. Usage example

2.1. GraphQL Client

// Import the library
import { gql } from 'graphql-request'
import createClient, { AuthMode } from '@remkoj/optimizely-graph-client/client'
import Router from '@remkoj/optimizely-graph-client/router'
import ChannelRepository from '@remkoj/optimizely-graph-client/channels'

// Prepare the query
const document = gql`query {
  Content {
    items {
      Name
      ContentLink {
        GuidValue
      }
      Language {
        Name
      }
    }
  }
}`

// Create an instance of the client, the configuration object may be omitted 
// when executing on Node.JS. If no configuration is provided, it will be read
// from the environment variables.
// The variable client will be of type: GraphQLClient
const client = createClient({
  single_key: "your_single_key"
})

// By default the client will always use AuthMode.Public, unless overridden by the
// second parameter of createClient. Use the updateAuthentication to change the
// authentication mode after creation
client.updateAuthentication(AuthMode.Public)

// Execute a GraphQL query, the second paramer can be used to send in variables
const result = await client.request(document)

// Use the Router to get all routes registered by Optimizely CMS
const router = new Router(client)
const allPaths = await router.getRoutes()

// Use the ChannelRepository to get all registered channels within Optimizely CMS
const channels = new ChannelRepository(client)
const allChannels = await channels.getAll()

2.2. GraphQL Client Authentication

Optimizely Graph allows restricted content to be queried, using either of the following patterns:

  • Graph Keys: Admin authentication using Graph Sercet Key and App Key
  • Token passthrough: Used by CMS preview/edit mode to provide a short lived access token to query the content to be previewed/edited. Read more
  • OpenID Connect: Used by the frontend to pass through OpenID Connect based JWT to authorize content. Read more
  • Generic Login: Used by the fronend to pass through the username/roles from a trusted identity provider. Read more

2.2.1. Graph Keys

The Graph Keys authentication mechanism can be enabled by providing the App Secret and App Key as part of the configuration. Then depending on your security policy, use either:

  • Basic Authentication: client.updateAuthentication(AuthMode.Basic)
  • HMAC Authentication: client.updateAuthentication(AuthMode.HMAC)

HMAC provides slightly better security as it both ensures message integrity and never transmits the App Secret in a decryptable form.

2.2.2. Token passthrough

This method of authentication is specific to Optimizely CMS, where the edit UI will provide a short-lived token that allows access to the content that is being edited. This only requires the Single Key to be known.

const tokenValue: string = ''; //Your token value here
client.updateAuthentication(tokenValue)

2.2.3. OpenID Connect

This method requires two steps, first, the client must be configured with the Turnstile Tenant ID, secondly the JWT Token of the OIDC provider must be added to the client.

const client = createClient({
  single_key: "your_single_key",
  tenant_id: "your_turnstile_tenant_id"
})
const tokenValue: string = ''; //Your OIDC JWT Token
client.updateAuthentication(tokenValue)

2.2.4. Token passthrough

This method works with non-OIDC compliant identity providers, but requires a trusted connection with Optimizely Graph. As such, it requires the Graph Keys to ensure that the client is authorized to pass in the username and roles directly.

The roles must be provided as a comma separated list, without spaces around the values. Both the username and roles must exactly match the roles and usernames defined in Optimizely CMS.

const client = createClient({
  single_key: "your_single_key",
  app_key: "your_app_key",
  secret: "your_secret"
})
client.setFrontendUser({
  username: "your_username",
  roles: "list_of_roles"
})

2.3. Admin API

Warning: The AdminAPI of Optimizely Graph requires your App Key & Secret as it allows full management of the service. When used in a browser, take all needed steps to prevent leaking of these credentials.

import createAdminApi from '@remkoj/optimizely-graph-client/admin'

// Create an instance of the client, the configuration object may be omitted 
// when executing on Node.JS. If no configuration is provided, it will be read
// from the environment variables.
const api = createAdminApi({
    single_key: "your single key",
    app_key: "your app key",
    secret: "your secret"
})

// Use the webhooks endpoint to list all registered webhooks
const hooks = await api.webhooks.listWebhookHandler()

3. Configuration

The following configuration options are available, the table lists both the environment variable as well as property within the configuration object.

Environment Configuration object Required Usage
OPTIMIZELY_GRAPH_GATEWAY gateway no The endpoint for Optimizely Graph
OPTIMIZELY_GRAPH_SINGLE_KEY single_key yes The key needed for public, read-only access
OPTIMIZELY_GRAPH_SECRET secret no The Optimizely Graph secret for write access, this value must never be made available in a browser
OPTIMIZELY_GRAPH_APP_KEY app_key no The Optimizely Graph app_key for write access, this value must never be made available in a browser
OPTIMIZELY_GRAPH_TENANT_ID tenant_id no The Optimizely Graph Tenant ID.

Only required when using OIDC Authentication
SITE_DOMAIN deploy_domain no The domain of the frontend
OPTIMIZELY_CMS_URL dxp_url yes The domain where the CMS has been installed
OPTIMIZELY_CMS_SCHEMA opti_cms_schema no The marker for the CMS schema version, which can be used by services and the implementation. Valid values are: OPTI-CMS-12 and OPTI-CMS-13. The default value is OPTI-CMS-13
OPTIMIZELY_GRAPH_QUERY_LOG query_log no Set to "true" to enable query output to the console
OPTIMIZELY_DEBUG debug no Set to "true" to enable verbose debug output to the console

3.1. Advanced Features

The Optimizely Graph Client has support for a number of the feature flags in Optimizely Graph and can enable/disable those on the fly.

The following features can currently be toggled:

  • Caching [Default: enabled]: Provides control over the service output cache, setting this to false will make all requests be evaluated in real time instead of being cached.
  • Stored queries [Default: enabled]: This will store the query to the underlying data store, so even when the output cache is invalidated, this will prevent the query to the data store to be regenerated. Warning: This feature does not work with cursors, so either disable it temporary or completely if you need cursors in you queries.
  • Recursive queries [Default: disabled]: When enabled it enables the execution of the @recursive(depth: n) directive. If compatible with the queries used, this can significantly reduce the number of queries needed to build a page.

The flags are controlled by the following instance methods & fields on the Client object:

  • updateFlags(newFlags, temporary): Update the flags for the instance. If there's roll-back information it will throw an Error. When temporary is enabled it will create a roll-back copy of the current flags prior to updating.
  • restoreFlags(): Restore the flags to the stored 'roll-back' copy, if there's no roll-back copy, no action is taken and no Error will be thrown.

Example

For server-side code, with access to environment variables, adjust according to your case.

// Import client & create instance
import createClient from '@remkoj/optimizely-graph-client/client';
const client = createClient();

// Example: Set the default for this client to add support for recursive queries
client.updateFlags({ recursive: true });

// Example: Temporary disable the query cache to allow queries with cursor
client.updateFlags({ queryCache: false }, true);
client.request(/* arguments */) // Or use - for example - an SDK / Function generated by GraphQL-Codegen
client.restoreFlags();

Readme

Keywords

none

Package Sidebar

Install

npm i @remkoj/optimizely-graph-client

Weekly Downloads

767

Version

3.2.0

License

Apache-2.0

Unpacked Size

259 kB

Total Files

273

Last publish

Collaborators

  • remkoj