Authentication
Authentication is not handled by Content Cloud. You can bring your own keys and use your own authentication services to provide JWTs for your users and services that Content Cloud uses to authorize requests to your spaces.
By default, spaces will require custom-signed JWTs to access content. If you want to use Auth0, Azure, AWS Cognito or another authentication service with our Content Cloud, please reach out to our support team to get you started.
Authorization
User IDs
User IDs are required to query for custom user data. Otherwise, no user ID is required.
Content Cloud uses the sub_id property of the JWT if one is provided and falls back to using the sub property of the JWT otherwise. We prefer the sub_id property, as that’s more likely to be an anonymized ID rather than personally identifiable information like an email address or user name.
Best practices
User IDs must be a string of up to 127 characters.
We don’t recommend using personal data like email addresses or names.
This can improve your privacy protection posture.
Not storing PII may simplify compliance and procurement for your organization or clients.
We recommend namespacing your user IDs to simplify future extendability of your application.
E.g.
auth0:...E.g.
MyBrandName:cognito:...
Share User IDs across different spaces and environments if it’s for the same person.
Shared settings
User IDs are not restricted to persons. If you want to store project settings or application settings for different devices for example, you can create a custom user data store ApplicationSettings / ProjectSettings / DeviceSettings and create JWTs that are unique for the different configurations you want to provide.
You can use this for A/B testing, for customizing the experience based on an end-users device etc.
In this case your user ID may instead be a unique device ID (a model or maker for example) or an environment ID etc. Be sure to avoid collisions with other type of IDs by using unique prefixes like device:....
To use shared settings, you may need to provide two JWTs to a user with different sub_id properties: one to query as the user and another one to query for these shared settings.
General JWT requirements
Content Cloud follows the standard structure for JWTs to work with a broad range of external authentication providers like Auth0:
scope, required: Claims are prefixed by type and provided as part of the scope property.
This can be a single string of space-concatenated scopes or an array of strings.
The following types are supported:
space:<ID>environment:<ID>permission:<NAME>service:<NAME>
Please see below for a list of permissions and services.
All other scopes will be ignored. We recommend prefixing other scopes with
custom:.You must provide exactly one space and at least one environment scope the user can access or the token will not provide any access at all.
aud, required: The audience of the token must be the base URL of your API without any path parameter.
This can be an array of URLs or just a single URL; non-matching URLs will be ignored.
iss, required: The issuer must be set to:
https://self-signed.auth.content-cloud.content-sync.io/<SPACE>/<CLIENT>This can be customized to match external providers, but you have to use this format for self-signed tokens.
iat, required: The issuing date time must be provided.
exp, required: The expiration date time must be provided.
permissions: You can optionally provide permissions and services under the permission property instead of including them in the scope.
Unknown permissions, services and environments are ignored.
Example
A JWT may look like this:
The example above provides redundant scopes, once in the scope and once in the permission claim. Providing them only once in either of them is enough; this is just for illustration purposes.
Algorithms
Content Cloud requires strong keys of at least 256 bytes (2048 bits) and supports the following formats:
symmetric: HS256, HS384, HS512
asymmetric: RS256, RS384, RS512
Content Cloud will use RS256 by default if nothing else is required.
Security considerations
The clock tolerance is set to 1 minute. This means:
Tokens are valid up to 60 seconds before their issuance date.
Tokens are valid for up to 60 seconds after their expiration date.
Access tokens are not allowed to last longer than a year.
The
nbfandjticlaims are allowed but will be ignored by Content Cloud.
External authentication providers
If you are already using an external auth provider or would like to streamline authentication across your applications, you can use any standard auth provider that can serve JWTs with custom audiences and scope properties, like Auth0 or open-source solutions.
Using standard auth providers can simplify user management, improve consistency, and avoid security risks.
Please see above for the JWT structure requirements. The issuer can be customized upon request.
Content Cloud supports and recommends using JWKS. JWKS works by only exposing the public key outside of your auth solution, so you don’t have to share any private secret with us and can rely solely on public keys.
Auto-generated JWTs
To sign a JWT, you can use our auto-generated TypeScript client that comes with a helper function for it. To sign a JWT, you need to first create a client in the space settings of the Content Cloud app. A client is used to store authentication information that allows Content Cloud to verify JWTs and authorize requests to your APIs.
After creating a new client, Generate a secret, then copy the provided secret to provide it as an environment variable to your backend. Never share the secret with your users or anywhere outside of your server-side project.
Secrets are not stored by our service and are only shown once when generating a client. If you have lost your secret, you can destroy it at the client and then generate a new one.
Manually generated JWTs
If you cannot use our auto-generated client in your project to sign JWTs, you can also sign your own JWTs with custom code. Please see above for the required structure of tokens. If you are unsure, you can still generate the auth client for TypeScript and transpile the code to work in your environment.
Testing JWTs
You can use the REST explorer to test access to the satellite APIs and validate permission settings for your queries.
Services
The services parameter controls which APIs the JWT provides access to. The following names are available:
Public or private satellite APIs
service:liveservice:cdnservice:assets
Private satellite APIs
service:devservice:previewservice:asset-previews
Private content management APIs
service:publisher
To learn more about the different APIs that are available, please see here.
Permissions
Content Cloud provides the following permissions that must be assigned to JWTs:
Frontend
permission:content:readAllow querying content, tags, and assets (excluding file content).
permission:content-type:readAllow querying content types.
permission:asset:read:fileAllow access to file content (all: download, embed, source, image).
permission:space:readAllow querying the current space, environments, and locales.
User data
permission:user-data:readAllow reading custom user data.
Requires setting a user ID.
Requires setting userDataContentTypes.
permission:user-data:writeAllow writing custom user data.
Requires setting a user ID.
Requires setting userDataContentTypes.
External links
permission:external-link:readAllow reading links to external instances of the entry.
E.g., all spaces have an external link to our backend for management.
E.g., content from Drupal receives one entry for every site using the content.
E.g., content from Drupal can use the source site’s canonical URL of the content in Drupal.
Previews (drafts)
permission:previewAllow access to preview/draft content.
Required when accessing the preview API.
Developer
permission:developerAllow access to the development API.
Allow downloading the schema definitions and auto-generated code.
Required for most commands of the Content Cloud CLI.
Management / backend
permission:organization:readRead name, feature flags from the organization of the space.
permission:space:writeUpdate the space, e.g. to change feature flags.
permission:content-type:writeCreate or update content types, including user data stores.
permission:content:writeCreate or update content entries.
DevOps
permission:client:readRead client settings except for the secret.
permission:client:writeUpdate client settings except for the secret.
permission:client:secretAllow access to the secret.
Must be used in combination with read or write permission.
Roles (RBAC)
If you are interested in Role-Based Access Control when integrating your own authentication methods, please reach out to our support team.
In most cases we recommend configuring your auth provider to provide permissions instead of roles, as this allows you to manage permissions centrally and can improve your security posture. Providers like Auth0 allow you to configure your own roles with permissions and pass on the permissions to our service based on which roles are assigned to a user.
Links
Links to other entries are always included in responses, regardless of user permissions, but users cannot request details of the linked entry. E.g. your content will include a sys.space.id property for content, but without the permission:space:read permission, a user cannot request the space details behind this ID. This is by design to not break data models and not break applications relying on Content Cloud APIs following the contracted data models.
With the exception of environments (custom IDs), locales (locale codes), and content types (machine names), entries are linked to by a random, 11+-character-long ID consisting of 62 alphanumeric characters.
Public APIs
By default, all APIs are private, but you can make certain APIs public and provide anonymous users default permissions. This can be controlled per environment. You can have one prod or public environment but keep your stage or dev environment private.
The following APIs can be made public:
Live
CDN
Assets
Please use this with caution, as it may incur additional charges from external parties using your APIs unexpectedly. We don’t recommend publicizing the Live API unless for very specific usage scenarios. Please contact us if you are unsure about what to make publicly available.
When choosing to expose a service, you can control what permissions an unauthorized user has. Following the principle of least privilege, we recommend exposing permissions that are as narrow as possible. The following permissions can be granted for anonymous requests:
Content: Read
Content Type: Read
Asset: Read File
External Link: Read
Space: Read
When an authorized user accesses your public API, they inherit both the public permissions configured for the API and their own, personal permissions.