Skip to content

Framing, CSP and cookies

What protects the help panel inside other sites, and what your app's own Content Security Policy must allow.

Off by default

Nothing under /embed exists, and /api/v1/help accepts no token, unless both OPEND_EMBED_SECRET (at least 32 characters) and OPEND_EMBED_ORIGINS are set. Each origin is a scheme, host and optional port, such as https://console.example.com, with no path or trailing slash.

The one exception is the help JSON API's anonymous answers on a public site: they are what any visitor of the site reads already, so they are always on, for any origin, and need no secret. A private site answers them with 401. See Help JSON API reference.

Who may frame what

  • Panel pages send frame-ancestors listing only the allowed origins, so no other site can frame them.
  • The docs site itself sends frame-ancestors 'none': it cannot be framed at all.
  • The panel runs no inline script. Its policy is default-src 'none'; script-src 'self'; img-src 'self' https: data:; style-src 'self' 'unsafe-inline'; connect-src 'self'; form-action 'self'; base-uri 'none', plus the frame-ancestors list.
  • Docs pages run no scripts at all.

Your app's Content Security Policy

If your app sends a CSP, allow the docs origin for the script and the frame:

script-src 'self' https://docs.example.com;
frame-src https://docs.example.com;

Apps that call the JSON API from the browser also need connect-src https://docs.example.com.

The panel's session

Inside your app, the panel is a third-party frame. Its session cookie, opend_embed, is HttpOnly, Secure, SameSite=None and Partitioned (CHIPS): it exists only under your app's site, never as a general session for the docs site, and expires after 60 minutes. The docs site's own session cookie is separate.

Because the cookie must be Secure, the docs site has to be served over HTTPS for the panel to keep a session. Browsers that block all third-party cookies, even partitioned ones, cannot keep a panel session; use the JSON API there.

What a host app can and cannot do

  • A host app vouches for who the user is. Entitlements still come from OpenD, so it cannot show a user more than their organization may see.
  • A token naming an email from another organization is refused.
  • Anyone with the embed secret can sign in as any registered reader. Keep it in your backend only, and rotate it by changing it on both sides.
  • There is one embed secret per deployment for now.
  • An app that needs only the public view of a public site needs no secret at all: it calls the JSON API anonymously.