API credentials and CLI authentication

KCWorks has two different authentication paths. Do not treat them as the same thing.

Path

Where it applies

How identity is established

HTTP API

REST requests, webhooks, outbound calls to Commons

Bearer / API key on the wire; the owning account’s permission policy on the target server

In-process CLI

invenio … commands inside this app

Flask-Principal identity (often system_identity) plus local permission policies; usually no API token

Credentials below are still kept distinct so each can be rotated or revoked without affecting the others.

Important

These credentials are separate on purpose. Do not reuse one in place of another, and do not introduce a shared fallback between them.

HTTP API authentication

Server-held integration credentials

These live in the server environment. They support unattended integrations on every request or record publication. They are the only credentials that must be present in a deployed environment for normal API/webhook traffic.

Variable

Used for

Minimum privilege

COMMONS_PROFILES_API_TOKEN

Outbound Profiles lookups (REMOTE_USER_DATA_API_ENDPOINTS, GROUP_COLLECTIONS_METADATA_ENDPOINTS) and inbound auth for the user/group sync webhooks (/api/webhooks/users/update and the deprecated /api/webhooks/user_data_update)

Outbound: read on members and groups at Profiles. Inbound: impersonates STATIC_API_TOKEN_USER_ID_PROFILES (svc-commons-profiles), which must hold the users-sync and groups-sync roles and must not hold admin or users-logout

COMMONS_SSO_LOGOUT_API_TOKEN

Inbound auth for the single-sign-out webhook (/api/webhooks/users/logout)

Impersonates STATIC_API_TOKEN_USER_ID_SSO (svc-commons-sso), which must hold only the users-logout role

COMMONS_SEARCH_API_TOKEN

Outbound provisioning of records and collections to the Commons search index (REMOTE_API_PROVISIONER_EVENTS)

Write on the Commons search documents endpoint

STATIC_API_TOKEN_USER_ID_PROFILES

Numeric user id impersonated by the Profiles static bearer on sync webhook routes

Must be svc-commons-profiles

STATIC_API_TOKEN_USER_ID_SSO

Numeric user id impersonated by the SSO static bearer on the logout webhook

Must be svc-commons-sso

Capability roles and the three service accounts (svc-commons-profiles, svc-commons-sso, svc-group-collections) are created automatically on app finalize by the owning packages. For an explicit ops run (or to print status):

invenio kcworks-users ensure-service-capabilities

After the accounts exist, point STATIC_API_TOKEN_USER_ID_PROFILES and STATIC_API_TOKEN_USER_ID_SSO at their numeric ids. Group-collection mutations use a normal OAuth token for svc-group-collections (not a static bearer). Full account / role / scope inventory: Service accounts and OAuth scopes.

Operator / client API credentials

These authenticate HTTP clients talking to a KCWorks REST API. They are not how in-process invenio commands authorize themselves on the local instance.

Client

How the credential is supplied

Authenticates against

Minimum privilege

kcworks-import-client

--api-key, or prompt / KCWORKS_IMPORT_API_KEY

The target KCWorks instance’s records API

Create records and upload files in the target collection

kcworks-import-client runs on an operator’s machine. It prompts for the key when neither the flag nor KCWORKS_IMPORT_API_KEY is set, and fails instead of prompting when stdin is not a terminal.

OAuth scopes (HTTP API)

KCWorks registers OAuth scopes and enforces them in two places: a central API before_request map for many RDM REST rules, and @require_oauth_scopes on webhook / group-collections views. Unmapped routes in the central map are not denied today. Permission policy on the token owner’s identity still applies in all cases — scopes narrow the token, capability roles gate the account. Route inventory: Service accounts and OAuth scopes. Registration and request-time details: OAuth scopes (developer notes).

In-process CLI authentication

invenio commands run inside the application process. They do not present a bearer token to the local REST API. Authorization is the identity passed into local services (CLI commands typically use system_identity) checked by local permission policies.

Command

Local authz

Outbound HTTP credential

invenio kcworks-records export-records

system_identity + RecordExportPermissionPolicy (can_export_records: elevated community roles when scoped to a community; subject user when an owner/contributor filter identifies their account; administration; system process)

None — local RDM services only

invenio kcworks-records import-test-records

Local import runs in-process (record importer services; no local API token)

--api-token (required) — bearer for reads from the remote instance that supplies sample metadata/files. Not used to authorize the local CLI itself

Record importer package CLI / service

Local services + importer permission policy

None

import-test-records is the hybrid case: local write path is CLI/service auth; the production (or other remote) fetch is ordinary HTTP API auth with a caller-supplied token. The application does not load that token from Flask config or the server environment — pass --api-token "$MY_SAMPLE_DATA_TOKEN" (or an equivalent function argument).

Note

If import-test-records were run without a remote token, the remote records API would still accept the request and return only public records. An incomplete sample set is worse than a failed command, so the CLI requires --api-token up front.

Credentials that are intentionally absent

Variable

Status

API_TOKEN

Removed. Export uses local services; sample import takes caller --api-token for the remote fetch only

API_TOKEN_PRODUCTION

Removed. Pass --api-token to import-test-records for the remote fetch

KCWORKS_EXPORTER_API_TOKEN

Removed. Export uses local services, not a REST bearer

KCWORKS_SAMPLE_DATA_API_TOKEN

Removed as application/config. Pass --api-token on import-test-records

RECORD_IMPORTER_API_TOKEN

Removed. Local importer uses in-process services

COMMONS_API_TOKEN

Removed. Superseded by COMMONS_PROFILES_API_TOKEN

STATIC_API_TOKEN_USER_ID

Removed. Use STATIC_API_TOKEN_USER_ID_PROFILES and STATIC_API_TOKEN_USER_ID_SSO

Local development

kcworks-startup.sh pulls server-held HTTP integration credentials from AWS Secrets Manager (see DEFAULT_SM_KEYS in that script). The keys must already exist in the JSON secret: the filter in scripts/kcworks_sm_secret_to_envfile.py fails in strict mode when a requested key is missing.

Caller-supplied remote-fetch tokens (and import-client API keys) are not pulled; supply them when you run the tool that needs them.