{"result":{"depiction_url":null,"edges":{"observes":{"objects":[{"created":"2026-10-06T13:35:39Z","object_id":{"id":1466,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_admin_menu","title":"observe_admin_menu\/3","uri":"https:\/\/zotonic.com\/id\/1466"},"seq":1},{"created":"2026-10-06T13:35:39Z","object_id":{"id":1984,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_auth_postcheck","title":"observe_auth_postcheck\/2","uri":"https:\/\/zotonic.com\/id\/1984"},"seq":2},{"created":"2026-10-06T13:35:39Z","object_id":{"id":2290,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_logon_options","title":"observe_logon_options\/3","uri":"https:\/\/zotonic.com\/id\/2290"},"seq":3},{"created":"2026-10-06T13:35:39Z","object_id":{"id":2413,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_auth_identity_types","title":"observe_auth_identity_types\/3","uri":"https:\/\/zotonic.com\/id\/2413"},"seq":4}],"predicate":{"id":2550,"is_a":["meta","predicate"],"name":"observes","title":{"_type":"trans","tr":{"en":"Observes"}},"uri":"https:\/\/zotonic.com\/id\/observes"}},"subject":{"objects":[{"created":"2026-10-06T13:35:39Z","object_id":{"id":2555,"is_a":["categorization","keyword","keyword_information_type"],"name":"zotonic_topic_reference","title":"Reference","uri":"https:\/\/zotonic.com\/id\/2555"},"seq":1},{"created":"2026-10-06T13:35:39Z","object_id":{"id":2562,"is_a":["categorization","keyword","keyword_audience"],"name":"zotonic_topic_site_administrator","title":"Site administrator","uri":"https:\/\/zotonic.com\/id\/2562"},"seq":2},{"created":"2026-10-06T13:35:39Z","object_id":{"id":2589,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_identity_and_accounts","title":"Identity and accounts","uri":"https:\/\/zotonic.com\/id\/2589"},"seq":3},{"created":"2026-10-06T13:35:39Z","object_id":{"id":2590,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_authentication","title":"Authentication","uri":"https:\/\/zotonic.com\/id\/2590"},"seq":4},{"created":"2026-10-06T13:35:39Z","object_id":{"id":2592,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_authorization_and_access_control","title":"Authorization and access control","uri":"https:\/\/zotonic.com\/id\/2592"},"seq":5},{"created":"2026-10-06T13:35:39Z","object_id":{"id":2599,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_api_and_integration","title":"API and integration","uri":"https:\/\/zotonic.com\/id\/2599"},"seq":6},{"created":"2026-10-06T13:35:39Z","object_id":{"id":2603,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_configuration","title":"Configuration","uri":"https:\/\/zotonic.com\/id\/2603"},"seq":7},{"created":"2026-10-06T13:35:39Z","object_id":{"id":2635,"is_a":["categorization","keyword","keyword_architecture"],"name":"zotonic_topic_module","title":"Module","uri":"https:\/\/zotonic.com\/id\/2635"},"seq":8},{"created":"2026-10-06T13:35:39Z","object_id":{"id":2681,"is_a":["categorization","keyword","keyword_technology"],"name":"zotonic_topic_oauth_2_0","title":"OAuth 2.0","uri":"https:\/\/zotonic.com\/id\/2681"},"seq":9}],"predicate":{"id":308,"is_a":["meta","predicate"],"name":"subject","title":{"_type":"trans","tr":{"en":"Keyword"}},"uri":"http:\/\/purl.org\/dc\/elements\/1.1\/subject"}}},"id":2766,"is_a":["text","documentation","reference","module"],"links":[{"rel":"self","target":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/2766"},{"rel":"hub","target":"https:\/\/zotonic.com\/.zotonic\/websub"}],"medium":null,"medium_url":null,"name":"doc_external_3_mod_sso_openidc","page_url":{"en":"https:\/\/zotonic.com\/docs\/2766\/mod_sso_openidc","x-default":"https:\/\/zotonic.com\/docs\/2766\/mod_sso_openidc"},"preview_url":null,"resource":{"version":27,"pivot_location_lat":null,"title":"mod_sso_openidc","is_authoritative":true,"body":"<p>Add OpenID Connect (OIDC) single sign-on providers to Zotonic&#39;s logon and\nsignup flow. Users authenticate at an external identity provider, and Zotonic\nlinks the provider&#39;s subject identifier to a local user identity.<\/p>\n<h2>Installation and provider setup<\/h2>\n<p>Install <code>zotonic_mod_sso_openidc<\/code> in <code>apps_user<\/code> or as a project dependency and\nenable <code>mod_sso_openidc<\/code> on the site. The module depends on <code>mod_authentication<\/code>\nand uses the <code>oidcc<\/code> library declared in its <code>rebar.config<\/code>. Authorization and\ncallback handling use Zotonic&#39;s OAuth2 service controllers.<\/p>\n<p>Open <strong>Auth → OpenID Connect Providers<\/strong> in the admin. Provider administration\nrequires administrator access or the <code>use.mod_sso_openidc<\/code> permission. This\npermission controls configuration; it is not required for visitors to log in.<\/p>\n<ol><li>Add a unique provider name and its discovery domain, without the <code>https:\/\/<\/code>\nprefix. Discovery fetches <code>https:\/\/&lt;domain&gt;\/.well-known\/openid-configuration<\/code>.<\/li><li>Register the Zotonic site as a client at the provider. Register the absolute\ncallback URL returned by <code>mod_sso_openidc:return_url(Context)<\/code> as its redirect\nURI. This uses the <code>oauth2_service_redirect<\/code> dispatch rule without a language\nprefix.<\/li><li>Enter the client ID and client secret, a display description, and optionally\na logo. Enable the provider and allow authentication.<\/li><li>Choose a display priority. Priority <code>99<\/code> omits the provider from the standard\nextra logon buttons; newly added providers start with this priority and are\ndisabled until configured.<\/li><\/ol>\n<p>The admin form keeps the provider name, discovery domain, and issuer fixed after\ncreation. Provider settings are stored in the <code>sso_openidc_provider<\/code> database\ntable rather than ordinary module configuration keys.<\/p>\n<h2>Authentication and signup settings<\/h2>\n<p>The implemented browser logon uses Authorization Code Flow: the browser returns\nan authorization code, which the server exchanges through <code>oidcc<\/code>. The admin\nform does not enable Client Credentials as an alternative browser logon flow.<\/p>\n<ul><li><strong>Scopes<\/strong> select requested claims. <code>openid<\/code> is always included. An empty\nscope configuration falls back to <code>openid email<\/code>; newly created provider\nrecords start with <code>openid email email_verified profile<\/code>.<\/li><li><strong>Additional user information<\/strong> enables retrieval from the provider&#39;s UserInfo\nendpoint to supplement ID-token claims.<\/li><li><strong>Require email<\/strong> rejects logon without an email address.<\/li><li><strong>Trust verified email<\/strong> treats returned email addresses as verified. Otherwise\nverification follows the returned <code>email_verified<\/code> value, defaulting to false\nwhen absent. The <code>verified_primary_email<\/code> claim is treated as verified.<\/li><li><strong>Add username\/password on signup<\/strong> requests a local username\/password identity\nfor a new signup. Connecting an identity to an existing account does not\nrequest this extra identity.<\/li><li><strong>Signup category<\/strong> selects the new user resource category, defaulting to <code>person<\/code>.<\/li><li><strong>Elevated ACR values<\/strong> configure requested authentication context classes.<\/li><\/ul>\n<h2>Domain routing and organization restrictions<\/h2>\n<p>The <strong>Domains<\/strong> field assigns primary email domains to a provider. The two-step\nlogon uses these assignments to direct users to that provider. Authentication\npostchecks reject other authentication services for controlled users with\n<code>user_external<\/code>; conflicting provider assignments also prevent acceptance.<\/p>\n<p>The separate <strong>Organizations<\/strong> field restricts which organizations may log in.\nThe module checks the <code>schac_home_organization<\/code> claim from the ID token or\nUserInfo. If it is absent, an email-domain fallback is used only when the\nprovider&#39;s trust-verified-email setting is enabled and the email is verified.\nA nonmatching organization returns <code>organization<\/code>; a required missing email\nreturns <code>email_required<\/code>. An empty organization list imposes no such restriction.<\/p>\n<h2>Identities and resource properties<\/h2>\n<p>The validated authentication uses service <code>mod_sso_openidc<\/code> and a service UID\nof <code>provider:subject<\/code>, where <code>subject<\/code> is the provider&#39;s <code>sub<\/code> claim. Provider\nnames therefore form part of the local identity key.<\/p>\n<table class=\"table\"><thead><tr><th>Claim<\/th><th>Zotonic value<\/th><\/tr><\/thead><tbody><tr><td><code>sub<\/code><\/td><td>Provider-prefixed service UID<\/td><\/tr><tr><td><code>email<\/code> or <code>verified_primary_email<\/code><\/td><td>Resource email and email identity<\/td><\/tr><tr><td><code>given_name<\/code><\/td><td><code>name_first<\/code><\/td><\/tr><tr><td><code>family_name<\/code><\/td><td><code>name_surname<\/code><\/td><\/tr><tr><td><code>name<\/code><\/td><td>Resource title<\/td><\/tr><\/tbody><\/table>\n<p>The module returns an <code>auth_validated<\/code> record to Zotonic&#39;s authentication\/signup\nintegration. Existing identities can log in or be connected to the current user;\nnew accounts follow the site&#39;s signup handling. Email identity verification is\ndetermined by the provider policy described above, not by SSO alone.<\/p>\n<h2>Integration points<\/h2>\n<p>The module observes <code>admin_menu<\/code>, <code>auth_identity_types<\/code>, <code>logon_options<\/code>, and\n<code>auth_postcheck<\/code>. It supervises <code>oidcc<\/code> provider workers, starts them for enabled\nproviders, and reloads their configuration after provider edits.<\/p>\n<p>Start authorization with the <code>oauth2_oidc_authorize<\/code> dispatch rule:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-django\">&lt;a href=&quot;{% url oauth2_oidc_authorize provider=provider.name %}&quot;&gt;Log in&lt;\/a&gt;\n<\/code><\/pre>\n<p>Use <code>m.sso_openidc.providers.list.auth<\/code> to obtain the public provider list.<\/p>","slug":"mod_sso_openidc","doc_module_config":[],"is_protected":false,"visible_for":0,"tz":"UTC","language":["en"],"doc_source_hash":"92c06fb19bfc18e22c87945f3db6ea2599fbec71ce9ddb0625a734666137a23c","doc_module_observers":[{"name":"admin_menu","page_name":"doc_notification_admin_menu"},{"name":"auth_identity_types","page_name":"doc_notification_auth_identity_types"},{"name":"auth_postcheck","page_name":"doc_notification_auth_postcheck"},{"name":"logon_options","page_name":"doc_notification_logon_options"}],"is_featured":false,"content_group_id":{"id":2551,"is_a":["meta","content_group"],"name":"content_group_imported_docs","title":"Imported documentation","uri":"https:\/\/zotonic.com\/id\/content_group_imported_docs"},"external_module_id":{"id":3,"is_a":[],"name":null,"title":null,"uri":"https:\/\/zotonic.com\/id\/3"},"git_url":"https:\/\/github.com\/driebit\/zotonic_mod_sso_openidc","category_id":{"id":320,"is_a":["meta","category"],"name":"module","title":"Modules","uri":"https:\/\/test.zotonic.com\/id\/320"},"doc_source_path":".\/src\/mod_sso_openidc.erl","publication_start":"2026-10-06T13:35:39Z","github_url":"https:\/\/github.com\/driebit\/zotonic_mod_sso_openidc","pivot_location_lng":null,"doc_source_kind":"external","name":"doc_external_3_mod_sso_openidc","is_unfindable":false,"is_published":true,"pivot_geocode":null,"external_module_title":"OpenIDC","created":"2026-10-06T13:35:39Z","uri":null,"doc_status":"current","is_dependent":false,"is_external_module":true,"publication_end":"9999-06-01T00:00:00Z","modifier_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"privacy":0,"doc_source_commit":"d47592abd3ac17d449e0ca6c82edc1d44a1c5607","creator_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"modified":"2026-10-06T13:35:39Z","title_slug":"mod_sso_openidc"},"uri":"https:\/\/zotonic.com\/id\/2766","uri_template":"https:\/\/zotonic.com\/id\/:id","websub":{"hub":"https:\/\/zotonic.com\/.zotonic\/websub","topic":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/2766"}},"status":"ok"}