Settings#

Every registry record the package reads.

All keys are under the pas.plugins.identity. prefix. Configuration lives in the registry, one record per setting, so a GenericSetup export describes a site field by field and one setting can be changed without rewriting the rest.

The Settings form in the Identity providers control panel edits the records in the next two sections, and the headings under each are its tabs, in the order they appear there. The derived records, the server layer's records and the per-provider records are not on that form and are described further down.

Site-wide#

Set by the pas.plugins.identity:default profile.

Login#

Key

Type

Default

What it does

callback_url

TextLine

/login-identity

The frontend route providers redirect back to. Matches the route the Volto add-on registers.

discovery_timeout

Int

10

Seconds to wait for a discovery document.

The timeout is here rather than with the portrait one because it fails the same way the callback does: metadata that does not arrive is a login that cannot start, while a portrait that does not arrive is a missing picture.

Both are required. The form refuses an empty callback URL, and a timeout below one second.

Portraits#

Key

Type

Default

What it does

sync_portraits

Bool

False

Fetch a portrait from the provider at sign-in.

portrait_timeout

Int

5

Seconds to wait for one.

portrait_max_bytes

Int

2097152

Refuse a portrait larger than this.

Audit log#

Key

Type

Default

What it does

audit_max_entries

Int

500

Entries the built-in log keeps.

audit_max_days

Int

180

Days the built-in log keeps.

audit_record_pii

Bool

False

Record personally identifying detail in audit entries.

audit_sinks

Tuple

('plugin',)

Which audit sinks to write to, in order. See The audit log.

Profiles and groups#

Where principals are filed, which of their workflow states count, and what a profile must carry before its owner is let past the gate.

Where principals are filed#

Key

Type

Default

What it does

profile_container_parent

TextLine

''

Path of the folder the profile container lives in, relative to the site root. Empty means the site root.

profile_container_id

TextLine

identity-profiles

Id of the folder holding user profiles.

profile_container_title

TextLine

Identity Profiles

Title used when this package creates the folder. Changing it later does not rename an existing one.

profile_container_type

TextLine

PrincipalsContainer

Portal type used when this package creates the folder. The parent must allow it. When it does not, creating the folder fails with an error naming the record, the type and the parent.

group_container_parent

TextLine

''

Same, for groups. Read only when group_container_id is set.

group_container_id

TextLine

''

Id of the folder holding groups. Empty means groups are filed with the profiles.

group_container_title

TextLine

Groups

Title used when this package creates the group folder.

group_container_type

TextLine

PrincipalsContainer

Portal type used when this package creates the group folder. The parent must allow it, as for profiles.

The group records default to the profile container's, so a site that files principals together sets none of them.

Which states count#

Key

Type

Default

What it does

profile_enumeration_states

Tuple

('incomplete', 'complete')

Profile workflow states visible to user enumeration and to the properties plugin.

group_enumeration_states

Tuple

('active',)

Group workflow states visible to group enumeration and granting membership.

Both are required, and the form refuses a list that names no state.

The profile gate#

Key

Type

Default

What it does

enforce_required_profile_fields

Bool

True

Redirect a user to their own edit form while their profile is incomplete.

confirm_email_at_first_login

Bool

False

Hold a profile incomplete until its owner confirms which verified address stands for them, when a first sign-in left it with more than one. The Volto add-on asks.

required_profile_fields

Tuple

()

Fields a profile must carry to count as complete. Empty means the fields the type itself marks required.

gate_exempt_paths

Tuple

()

Extra view names the gate never redirects, matched on the last path segment.

See Profiles and groups for what each state means and which routes are exempt already.

Derived records#

The four records core reads to create users and groups. They are declared read-only, so the Settings form does not show them and a save through the control panel never writes them.

Key

Type

Default

What it does

user_content_type

TextLine

''

Content type used for user profiles.

user_container_path

TextLine

''

Where profiles are filed.

group_content_type

TextLine

''

Content type used for groups.

group_container_path

TextLine

''

Where groups are filed.

All four are empty by default. A subscriber sets the two paths at install and again whenever a record under Where principals are filed changes: set the container records, not these. The install handler fills the two types with UserProfile and UserGroup only when they are empty, so a site's own profile may name its own. See Users and groups as content.

Server layer#

Present only where pas.plugins.identity.server:default has been applied.

Key

Type

Default

What it does

server_issuer

TextLine

''

The URL identifying this authorization server. Never derived from the portal URL.

server_consent_url

TextLine

''

Where the browser is sent to approve a request.

server_access_token_ttl

Int

900

Access token lifetime, in seconds.

server_refresh_token_ttl

Int

1209600

Refresh token lifetime, in seconds—14 days.

server_clients

Text

''

The client registry. Managed through @identity-clients, not by hand.

server_signing_keys

Text

''

The signing key ring. Managed through @identity-keys, not by hand.

server_unreleased_groups

Tuple of Choice

()

Groups left out of the groups claim for every relying party. Adds to a floor this server always applies; it does not replace it.

Only the two lifetimes are written by the install profile. server_clients and server_issuer are deliberately left out, because an empty <value> imports as None while omitting the key takes the empty string the schema field declares. A site with no clients and no issuer is the correct initial state: the server signs nothing until it is told what it is called.

Set server_issuer yourself, under Server settings in the OAuth clients control panel. See About federation for why it is configured rather than derived.

The control panel carries five of these records: the issuer, the consent screen, both lifetimes and the unreleased groups. server_clients and server_signing_keys are not on it, and @controlpanels/identity-clients neither serves them nor writes them. The key ring holds private keys.

The panel refuses an issuer that relying parties would not match:

Refused

Why

A trailing slash

Relying parties compare the issuer byte for byte, and the server publishes it without one.

No scheme or no host

Every endpoint the discovery document names is built from it.

A query or a fragment

OpenID Connect Discovery forbids them.

Leading or trailing space

Invisible in the form, and not what is published: the server strips it when it reads the record.

The rule is on the panel, not on the record. A value written straight to the registry is not checked, and the server strips spaces and a trailing slash when it reads one.

The two defaults are chosen, not arbitrary:

  • 900 seconds for an access token. There is no denylist, so this doubles as the worst case between revoking a client and the last token minted for it expiring.

  • 14 days for a refresh token. They rotate on every use, so this is how long a client may stay away before a person has to sign in again—long enough that a daily integration never sees a login page, short enough that an abandoned one stops working inside a sprint.

Per provider#

Pattern:

pas.plugins.identity.providers.<provider_id>.<field>

<field> is a field of that provider's driver settings schema. Which fields exist, and what type each one is, comes from the driver at runtime.

Provider records belong to no interface—each carries its own field type. That is why a GenericSetup profile writing them needs a field element per record unless it names an interface that declares them.

Fields every provider has#

Key

Type

Default

What it does

driver

TextLine

''

Which driver this provider uses.

title

TextLine

''

What the login button says.

enabled

Bool

True

Whether the provider works at all.

show_in_login

Bool

True

Whether the login page offers a button for it.

icon

Bytes

None

An SVG document, sanitized on save.

background_color

TextLine

''

Button background, such as #24292f.

foreground_color

TextLine

''

Button text colour.

order

Int

0

Position among the buttons. Set by dragging the provider list rather than on the provider's form.

propertymap

Dict

{}

Claim path → Profile field. The target is a Choice over the fields of the site's user type and its behaviors, except the login, the userid, membership, roles, addresses and the portrait; any other value is refused.

groupmap

Dict

{}

Provider group name → local group id. The API refuses a local group the site does not have; an import stores it and logs a warning.

Both default to True, so a provider added through the API without saying otherwise is enabled and shown.

enabled and show_in_login are different questions. An enabled provider that is not shown still signs people in and is still linkable from a user's own sign-in methods page; it has no button.

Fields from the driver#

Under pas.plugins.identity.providers.<id>.config.<field>.

Every OAuth2 driver—IOAuth2Settings#

Field

Type

Required

Default

Tab

client_id

TextLine

yes

—

Settings

client_secret

Password

yes

—

Settings

scope

Tuple

no

()

Settings

userid_source

Choice

no

'uuid'

Accounts

create_user

Bool

no

True

Accounts

auto_link_by_email

Bool

no

False

Accounts

trust_email_verification

Bool

no

False

Accounts

accept_string_booleans

Bool

no

False

Accounts

An empty scope means the driver's own default is used. See Shipped drivers.

GitHub adds—IGitHubSettings#

Field

Type

Required

Default

Tab

address_preference

Tuple

no

()

Accounts

Each entry is * or @ followed by a domain. Anything else is refused when the provider is saved. See GitHub.

OpenID Connect drivers add—IOIDCSettings#

Field

Type

Required

Default

Tab

issuer

TextLine

yes

—

Settings

group_claim

TextLine

no

''

Groups

allowed_groups

Tuple

no

()

Groups

sync_groups

Bool

no

True

Groups

picture_over_http

Bool

no

False

Profile

Applies to oidc-generic and plone-identity.

GitHub—IGitHubSettings#

Inherits IOAuth2Settings and adds no fields. There is no issuer: GitHub is not an OpenID Connect provider and the endpoints are built into the driver.

Secrets are exported in the clear#

A GenericSetup export carries a client secret as its stored value. The record is a plone.registry.field.Password, which marks it as a secret wherever a record is inspected; marking is not encryption.

So an export of your provider configuration is enough to rebuild a working site, and is itself a credential. Read one before committing it anywhere.

See About secrets.