Shipped drivers#

A driver is registered as a named ZCA utility providing IDriver, and the utility name is the driver id. Six ship with the package.

Driver id

Title

Provider

oidc-generic

OpenID Connect

Any conforming OpenID Connect provider.

plone-identity

Plone site

Another Plone site running the [server] layer. Built on oidc-generic.

keycloak

Keycloak

A Keycloak realm. Built on oidc-generic.

google

Google

Google, through discovery at an issuer the driver fixes.

github

GitHub

GitHub OAuth2. Not an OpenID Connect provider.

email

Email

No external provider: this site emails a single-use signed token.

Attributes#

Every column is a class attribute on the driver, and every one of them is only a default. What a given deployment trusts a given provider with is a fact about the deployment, so the operator can override each one per provider.

oidc-generic

plone-identity

keycloak

google

github

email

Settings schema

IOIDCSettings

IPloneIdentitySettings

IKeycloakSettings

IOAuth2Settings

IGitHubSettings

IEmailSettings

Endpoints from

discovery, at an issuer you type

discovery, at an issuer you type

discovery, at an issuer you type

discovery, at the issuer the driver declares

the four the driver declares

none

Default scope

openid email profile

openid email profile address

openid email profile

openid email profile

read:user user:email

—

Subject read from

sub

sub

sub

sub

id, then node_id

email

Default userid source

uuid

username

username

uuid

username

uuid

Trusts email_verified by default

no

no

yes

yes

yes

—

Default group claim

groups

groups

groups

none

none

none

Can be linked from a form

yes

yes

yes

yes

yes

no

email is the only driver a user cannot start a link against from a form: its subject is an address the user would type, and a free-text box there is a box for claiming any address at all. Its addresses come from the profile instead.

Which settings each schema carries#

This is what decides which fields a provider's form shows. A driver on IOAuth2Settings has no issuer field and no group fields at all.

Schema

Extends

Adds

IDriverSettings

Interface

nothing

IOAuth2Settings

IDriverSettings

client_id, client_secret, scope, userid_source, trust_email_verification, create_user, accept_string_booleans, auto_link_by_email

IOIDCSettings

IOAuth2Settings

issuer, group_claim, allowed_groups, sync_groups, picture_over_http

IGitHubSettings

IOAuth2Settings

address_preference

IPloneIdentitySettings

IOIDCSettings

nothing but a different issuer description

IKeycloakSettings

IOIDCSettings

nothing but a different issuer description

IEmailSettings

IDriverSettings

token_ttl, rate_limit_per_hour

Two consequences worth reading off that table:

  • google and github have no group settings. Not a group claim you can name, not an allowed-groups list, not a sync switch. Neither provider sends groups this package can read.

  • email has no account settings. No create_user, no auto_link_by_email, no trust_email_verification. A missing create_user reads as True, so an email provider always creates accounts.

See Settings for each field's type and default, and The provider form for how they are arranged in the control panel.

Default property maps#

Seeded into a new provider's attribute mapping, written against the normalized claim names rather than any one provider's.

Driver

Map

oidc-generic, keycloak, google

fullname → fullname

github

that, plus bio → description, blog → home_page, location → location

plone-identity

that first row, plus website → home_page, description → description, address.formatted → location

email

empty

A map never writes an address or a portrait, see Settings, so no driver seeds a row for either. Both arrive on a login regardless: an address is appended to the profile's own list, and a portrait is fetched from the picture_url claim when sync_portraits is on.

No driver maps username. Providers publish it; a Profile has no such field.

Default icons#

Every shipped driver has a login-button icon. A provider with no icon of its own is drawn with its driver's, and an icon uploaded on the provider replaces it.

Driver

File

Copied from

Licence

github

github.svg

volto-authomatic, github.svg

MIT

google

google.svg

volto-authomatic, google.svg

MIT

oidc-generic

oidc-generic.svg

volto-authomatic, openid.svg

MIT

plone-identity

plone-identity.svg

Volto, plone.svg

MIT

keycloak

keycloak.svg

Volto, finger-print.svg

MIT

email

email.svg

Volto, email.svg

MIT

The default is resolved when a provider is drawn, in @login-providers and @identities, and never stored. The provider's record, the control panel form and an export carry only an uploaded icon. @identity-drivers serves each driver's default, and the form's Icon field shows it until one is uploaded.

A default passes through the same sanitizer as an upload. A third-party driver names its own with icon_resource, as package:path. One that does not resolve, or is not an SVG document, is logged and drawn as no icon.

Driver notes#

github

Not an OpenID Connect provider: it publishes no discovery document, so the driver declares its four endpoints outright. GET /user omits the address of anybody who marked it private and carries no email_verified at all, so the driver names GET /user/emails as an enrichment endpoint and the flow fetches it after userinfo. That call is best-effort: a narrowed scope answers 403, and a login is not the moment to fail over an address. Every address on the account goes onto the person's profile, the account's own primary first.

google

The driver declares the issuer, https://accounts.google.com, rather than asking for it. There is nothing to configure and nothing to get wrong. Its userinfo carries a name, an address and a picture, and nothing a Profile's other three fields could hold, which is why its map has one row.

oidc-generic

The one driver that declares neither endpoints nor an issuer: both come from the operator, because "any conforming provider" is exactly the case where the package knows nothing in advance. Its map has one row for the same reason: website and address.formatted are registered OIDC claims, but whether a given provider fills them in is not something a generic driver can know.

plone-identity

A peer is a conforming OIDC provider and gets no special path through the flow. What the driver carries is the configuration a peer can be known in advance to want: the address scope, a map for every claim the peer actually releases, and the peer's preferred_username as the local userid, so one person is recognisable by the same name across the federation.

keycloak

Like a peer, a realm is a conforming OIDC provider and gets no special path through the flow. The driver carries the realm's preferred_username as the local userid, and trusts its email_verified, since a realm is usually run by the organization running the site. Its scope and map are the generic ones: under openid email profile a default realm releases a name, a username and an address, and nothing a Profile's other three fields could hold. Its issuer is the realm URL, https://<server>/realms/<realm>; the server root serves no discovery document.

email

See below.

To add a driver for a provider not listed here, see Write a driver.

Group claims#

A driver declares whether its providers assert group membership, and that declaration is what offers the group map in the control panel. A driver with no group claim offers no field to name one, and a group map stored against such a provider grants nothing rather than guessing at a claim name.

groups is not a registered OIDC claim. It is the name Keycloak, Okta and Entra all use, and the one this package's own [server] layer releases. Set a dotted path for a provider that nests them, such as realm_access.roles.

Mapping and revocation are covered in Map provider groups.

The email driver#

Property

Value

Token lifetime

At most fifteen minutes, whatever token_ttl says.

Reuse

Single use. The token is burned server side.

Rate limit

Per address and per IP.

Response to an unknown address

Identical to the response for a known address.

The rate limit applies per IP as well as per address because limiting per address alone misses the enumeration attack, which uses a fresh address every time. The send endpoint answers identically whether or not the address belongs to an account: a different answer would be an account-existence oracle.

A magic-link sign-in is the only email verification this package trusts for linking decisions. See About email verification.