Authentication & Authorization
Precept relies on a "bring your own IdP" model — the only requirement is that your IdP supports OAuth 2.0 / OpenID Connect. Any OIDC-compliant provider will work, including (but not limited to):
- Auth0 / Okta
- Amazon Cognito
- Google Identity Platform
- Microsoft Entra ID
- Keycloak
- ORY Hydra
Configuring Your IdP
1. Register Precept as an Application
In your IdP, create a new Single Page Application (SPA) registration with the following settings:
| Setting | Value |
|---|---|
| Application type | Single Page Application (SPA) |
| Allowed callback URL | https://<your-precept-host>/ |
| Allowed logout URL | https://<your-precept-host>/ |
| Allowed grant types | Authorization Code (with PKCE) |
The UI uses the Authorization Code flow with PKCE — no client secret is needed.
2. Register an API / Resource Server
Create an API (or "resource server") entry in your IdP to represent the Precept backend. The identifier you choose here becomes the audience value in Precept's configuration.
For example, you might use https://precept.example.com/api as the identifier.
3. Configure Precept
Point Precept at your IdP by setting the http.auth.* server options. The three required options are:
http.auth.issuer-base-url— your IdP's issuer URL (must expose/.well-known/openid-configuration)http.auth.audience— the API identifier registered in your IdPhttp.auth.ui.client-id— the OAuth 2.0 client ID for the Precept UI
See the Server Options reference for the full list of http.auth.* options, including optional settings for authority override, login query parameters, query parameter whitelisting, and the requested login scope.
Example Configuration
# Required
PRECEPT_HTTP_AUTH_ISSUER_BASE_URL=https://example.us.auth0.com/
PRECEPT_HTTP_AUTH_AUDIENCE=https://precept.example.com/api
PRECEPT_HTTP_AUTH_UI_CLIENT_ID=abc123def456
# Optional — pass the audience to the IdP - required by Auth0 during login
PRECEPT_HTTP_AUTH_UI_QUERY_PARAMS='{"audience":"https://precept.example.com/api"}'
# Optional — allow the "connection" param to be set via URL
PRECEPT_HTTP_AUTH_UI_QUERY_PARAMS_WHITELIST=connection
# Optional — override the OAuth2 scope requested at login
PRECEPT_HTTP_AUTH_UI_SCOPE="openid profile email"Provider-Specific Notes
Auth0 / Okta
Auth0 requires the audience parameter at login time to issue an access token. Set PRECEPT_HTTP_AUTH_UI_QUERY_PARAMS to include it:
PRECEPT_HTTP_AUTH_UI_QUERY_PARAMS='{"audience":"https://precept.example.com/api"}'If you use Auth0 Organizations or enterprise connections, whitelist the relevant param so it can be passed dynamically:
PRECEPT_HTTP_AUTH_UI_QUERY_PARAMS_WHITELIST=connectionAmazon Cognito
Cognito's OIDC endpoints span two hostnames:
| Endpoint | Host |
|---|---|
Discovery (/.well-known/openid-configuration), JWKS | cognito-idp.<region>.amazonaws.com |
| Token, UserInfo | <prefix>.auth.<region>.amazoncognito.com |
The issuer origin (cognito-idp.<region>.amazonaws.com) is allowed automatically — Precept derives it from your configured authority — and it is the same host that serves discovery and JWKS. The token/userinfo host cannot be derived from the issuer, so you must allow it explicitly via connect-src:
# <prefix> is your Cognito hosted-UI domain prefix; its region must match the issuer's
PRECEPT_HTTP_AUTH_ISSUER_BASE_URL=https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxxx
PRECEPT_HTTP_UI_CSP_DIRECTIVES='{"connect-src":["https://<prefix>.auth.us-east-1.amazoncognito.com"]}'Keycloak
Set the issuer base URL to your realm endpoint:
PRECEPT_HTTP_AUTH_ISSUER_BASE_URL=https://keycloak.example.com/realms/preceptMicrosoft Entra ID
Use the v2.0 endpoint as the issuer:
PRECEPT_HTTP_AUTH_ISSUER_BASE_URL=https://login.microsoftonline.com/<tenant-id>/v2.0Content Security Policy
The UI is served with a Content Security Policy that restricts which origins the browser may contact. Your IdP's origin (from http.auth.issuer-base-url / http.auth.ui.authority) is allowed automatically.
If your deployment needs the UI to reach additional origins — a split-host IdP (see Amazon Cognito above), web analytics, a custom CDN, etc. — add them with PRECEPT_HTTP_UI_CSP_DIRECTIVES. It takes a JSON object mapping CSP directive names (kebab-case) to arrays of sources, and is append-only: your sources are added to the built-in policy, never replacing it, so you cannot accidentally weaken or break the defaults.
PRECEPT_HTTP_UI_CSP_DIRECTIVES='{"connect-src":["https://analytics.example.com"],"script-src":["https://cdn.example.com"]}'Sources must be valid CSP tokens, including quotes around keywords (e.g. "'unsafe-inline'"). An invalid policy is rejected at server startup.
Authorization & Policies
Precept uses a permission-based authorization model via custom JWT claims. Your IdP can embed a https://precept.sh/policy claim in the access token containing an array of permission strings.
Available Permissions
| Permission | Description |
|---|---|
config.global.write | Modify global configuration settings for any PDM |
pdm.create | Upload and activate new PDMs |
pdm.delete | Remove existing PDMs and their configuration |
telemetry.read | Read the Performance page and its API. Shows error data of all tenants. |
Policies are for administering the Precept server and adding & removing integrations. With no policy claims, tokens authorize end-consumer usage of the platform, enabling usage of API calls to any integration which either:
- A user has individually authenticated to, or
- An admin has configured with global or org-level credentials
WARNING
Give telemetry.read only to administrators who are cleared to see the data of all tenants. The Performance page shows errors from every tenant. These errors can contain downstream response bodies, headers, URLs and stack traces. Precept does not redact this data. See Observability.
A user without telemetry.read does not see the Performance page in the sidebar. If this user opens /performance directly, the page shows a message and requests no data. The /rest/telemetry API responds with status 403 to this user.
If administrators use the Performance page, add telemetry.read to their policy claim before you upgrade Precept.
Setting Up Policies
To assign policies, configure your IdP to inject the https://precept.sh/policy claim into the access token based on user roles or group membership.
Precept reads the claim from the access token, not the ID token. Precept validates the Bearer access token that the UI sends to the API. Emit the claim into that token.
The claim must be an array of permission strings:
{
"https://precept.sh/policy": [
"config.global.write",
"pdm.create",
"pdm.delete",
"telemetry.read"
]
}Map each Precept role to a group in your IdP. Then emit the permission array for members of that group. If a user is in more than one group, emit the union of their permissions as one flat array. Precept reads each string as one permission. This works with any OIDC provider, including Microsoft Entra ID, Okta, Amazon Cognito, and Keycloak.
The example below uses Auth0 Actions. The claim shape is the same for any provider, so use it as a reference even if you use a different IdP.
Example: assign role-based policies with Auth0 Actions
This example configures Auth0 to inject the policy claim into access tokens based on a user's role.
Prerequisites
- An Auth0 tenant with an API (resource server) configured.
- Admin access to the Auth0 Dashboard.
1. Create a role
- Go to Auth0 Dashboard > User Management > Roles.
- Click Create Role.
- Set the name to
https://precept.sh/role/admin.
2. Assign the role to users
- Go to Auth0 Dashboard > User Management > Users.
- Select a user.
- Open the Roles tab.
- Click Assign Roles and select
https://precept.sh/role/admin.
3. Create an Action
- Go to Auth0 Dashboard > Actions > Library.
- Click Create Action > Build from scratch.
- Set the name to
Add Precept Policy Claims Based on Roles. - Set the trigger to
Login / Post Login. - Replace the default code with the following:
exports.onExecutePostLogin = async (event, api) => {
const namespace = "https://precept.sh";
// Grant admin permissions to users in the admin role.
if (event.authorization?.roles.includes(`${namespace}/role/admin`)) {
api.accessToken.setCustomClaim(`${namespace}/policy`, [
"config.global.write",
"pdm.create",
"pdm.delete",
"telemetry.read",
]);
}
};- Click Save Draft, then Deploy.
4. Attach the Action to the login flow
- Go to Auth0 Dashboard > Actions > Triggers.
- Select the post-login flow.
- Drag the
Add Precept Policy Claims Based on RolesAction onto the graph, between Start and Complete. - Click Apply.
Verify
When a user with the admin role signs in, the access token contains the claim:
{
"iss": "https://your-domain.auth0.com/",
"sub": "auth0|USER-ID",
"aud": "YOUR_API_AUDIENCE",
"https://precept.sh/policy": [
"config.global.write",
"pdm.create",
"pdm.delete",
"telemetry.read"
]
}If the claim does not appear, confirm the Action is attached to the login flow, and confirm the role name matches https://precept.sh/role/admin exactly. Decode the token with a tool such as jwt.io to inspect its contents.
OIDC Scopes
The UI requests the following OIDC scopes during login:
openid— required for OIDCprofile— user display nameemail— user email address
Ensure these scopes are enabled for your application in your IdP.