{"result":{"depiction_url":null,"edges":{"observes":{"objects":[{"created":"2026-09-09T13:47:46Z","object_id":{"id":1440,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_logon_submit","title":"observe_logon_submit\/2","uri":"https:\/\/zotonic.com\/id\/1440"},"seq":1},{"created":"2026-09-09T13:47:46Z","object_id":{"id":1442,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_request_context","title":"observe_request_context\/3","uri":"https:\/\/zotonic.com\/id\/1442"},"seq":2},{"created":"2026-09-09T13:47:46Z","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":3},{"created":"2026-09-09T13:47:46Z","object_id":{"id":1835,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_auth_options_update","title":"observe_auth_options_update\/3","uri":"https:\/\/zotonic.com\/id\/1835"},"seq":4},{"created":"2026-09-09T13:47:46Z","object_id":{"id":2158,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_m_config_update","title":"observe_m_config_update\/2","uri":"https:\/\/zotonic.com\/id\/2158"},"seq":5},{"created":"2026-09-09T13:47:46Z","object_id":{"id":2167,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_auth_validated","title":"observe_auth_validated\/2","uri":"https:\/\/zotonic.com\/id\/2167"},"seq":6},{"created":"2026-09-09T13:47:46Z","object_id":{"id":2283,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_auth_client_logon_user","title":"observe_auth_client_logon_user\/2","uri":"https:\/\/zotonic.com\/id\/2283"},"seq":7},{"created":"2026-09-09T13:47:46Z","object_id":{"id":2289,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_auth_client_switch_user","title":"observe_auth_client_switch_user\/2","uri":"https:\/\/zotonic.com\/id\/2289"},"seq":8},{"created":"2026-09-09T13:47:46Z","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":9}],"predicate":{"id":2550,"is_a":["meta","predicate"],"name":"observes","title":{"_type":"trans","tr":{"en":"Observes"}},"uri":"https:\/\/zotonic.com\/id\/observes"}},"references":{"objects":[{"created":"2020-05-30T05:48:06Z","object_id":{"id":1536,"is_a":["text","documentation","developerguide"],"name":"doc_developerguide_access_control","title":{"_type":"trans","tr":{"en":"Keep permission checks at the boundary"}},"uri":"https:\/\/zotonic.com\/id\/1536"},"seq":1000000}],"predicate":{"id":332,"is_a":["meta","predicate"],"name":"references","title":{"_type":"trans","tr":{"en":"References"}},"uri":"https:\/\/zotonic.com\/id\/references"}},"subject":{"objects":[{"created":"2026-09-09T13:47:46Z","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-09-09T13:47:46Z","object_id":{"id":2564,"is_a":["categorization","keyword","keyword_audience"],"name":"zotonic_topic_backend_developer","title":"Backend developer","uri":"https:\/\/zotonic.com\/id\/2564"},"seq":2},{"created":"2026-09-09T13:47:46Z","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-09-09T13:47:46Z","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-09-09T13:47:46Z","object_id":{"id":2635,"is_a":["categorization","keyword","keyword_architecture"],"name":"zotonic_topic_module","title":"Module","uri":"https:\/\/zotonic.com\/id\/2635"},"seq":5},{"created":"2026-09-09T13:47:46Z","object_id":{"id":2652,"is_a":["categorization","keyword","keyword_task"],"name":"zotonic_topic_authenticate","title":"Authenticate","uri":"https:\/\/zotonic.com\/id\/2652"},"seq":6},{"created":"2026-09-09T13:47:46Z","object_id":{"id":2685,"is_a":["categorization","keyword","keyword_quality"],"name":"zotonic_topic_security","title":"Security","uri":"https:\/\/zotonic.com\/id\/2685"},"seq":7}],"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":1306,"is_a":["text","documentation","reference","module"],"links":[{"rel":"self","target":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/1306"},{"rel":"hub","target":"https:\/\/zotonic.com\/.zotonic\/websub"}],"medium":null,"medium_url":null,"name":"doc_module_mod_authentication","page_url":{"en":"https:\/\/zotonic.com\/docs\/1306\/mod_authentication","x-default":"https:\/\/zotonic.com\/docs\/1306\/mod_authentication"},"preview_url":null,"resource":{"version":3391,"pivot_location_lat":null,"title":"mod_authentication","is_authoritative":true,"body":"<p>This module contains the main Zotonic authentication mechanism. It contains the logon and logoff controllers, and\nimplements the various hooks as described in the <a href=\"\/id\/doc_developerguide_access_control#guide-auth\">Access control<\/a> manual.<\/p>\n<p>Configuration keys:<\/p>\n<table class=\"table\"><thead><tr><th>Key<\/th><th>Description<\/th><\/tr><\/thead><tbody><tr><td><code>mod_authentication.password_min_length<\/code><\/td><td>The minimum length of passwords. Defaults to 8; set this to an integer value.<\/td><\/tr><tr><td><code>mod_authentication.is_rememberme<\/code><\/td><td>Set this to <code>1<\/code> to check the <em>remember me<\/em> checkbox per default.<\/td><\/tr><tr><td><code>mod_authentication.is_one_step_logon<\/code><\/td><td>Normally a two-step logon is used, first the username is requested, then the password is requested. In between the server checks the username and is able to show alternative authentication methods based on the username. Set this to <code>1<\/code> to show the username and password field at once, and disable the display of alternative authentication methods.<\/td><\/tr><tr><td><code>mod_authentication.is_signup_confirm<\/code><\/td><td>Set to <code>1<\/code> to force user confirmation of new accounts. This is useful when using 3rd party authentication services. If a new identity is found then a new account is automatically added. With this option set the user will be asked if they want to make a new account. This prevents duplicate accounts when using multiple authentication methods.<\/td><\/tr><tr><td><code>mod_authentication.reset_token_maxage<\/code><\/td><td>The maximum age of the emailed reset token in seconds. Defaults to 48 hours (172800 seconds). This must be an integer value.<\/td><\/tr><tr><td><code>mod_authentication.email_reminder_if_nomatch<\/code><\/td><td>On the password reset form, a user can enter their email address for receiving an email to reset their password. If a user enters an email address that is not connected to an active account then we do not send an email. If this option is set to <code>1<\/code> then an email is sent. This prevents the user waiting for an email, but enables sending emails to arbitrary addresses.<\/td><\/tr><tr><td><code>mod_authentication.auth_secret<\/code><\/td><td>The secret used to sign authentication cookies. This secret is automatically generated. Changing this secret will invalidate all authentication cookies.<\/td><\/tr><tr><td><code>mod_authentication.auth_anon_secret<\/code><\/td><td>The secret to sign authentication cookies for the anonymous user. This secret is automatically generated. Changing this secret will invalidate all authentication cookies for anonymous users.<\/td><\/tr><tr><td><code>mod_authentication.auth_user_secret<\/code><\/td><td>The secret to sign authentication cookies for the identified users if there is no database to store individual secrets.<\/td><\/tr><tr><td><code>mod_authentication.auth_autologon_secret<\/code><\/td><td>The secret to sign <em>remember me<\/em> cookies. This secret is automatically generated. Changing this secret will invalidate all <em>remember me<\/em> cookies for all users.<\/td><\/tr><\/tbody><\/table>\n<p>Related configurations:<\/p>\n<table class=\"table\"><thead><tr><th>Key<\/th><th>Description<\/th><\/tr><\/thead><tbody><tr><td><code>site.password_force_different<\/code><\/td><td>Set to <code>1<\/code> to force a user picking a different password if they reset their password.<\/td><\/tr><tr><td><code>site.ip_allowlist<\/code><\/td><td>If the admin password is set to <code>admin<\/code> then logon is only allowed from local IP addresses. This configuration overrules the <code>ip_allowlist<\/code> global configuration and enables other IP addresses to login as <code>admin<\/code> if the password is set to <code>admin<\/code>.<\/td><\/tr><\/tbody><\/table>\n<h2>Accepted Events<\/h2>\n<p>This module handles the following notifier callbacks:<\/p>\n<ul><li><code>observe_admin_menu<\/code>: Contribute module entries to the admin menu tree.<\/li><li><code>observe_auth_client_logon_user<\/code>: Send a request to the client to login a user using <code>z_context:client_topic<\/code>.<\/li><li><code>observe_auth_client_switch_user<\/code>: Send a request to the client to switch users using <code>z_acl:sudo_user<\/code>.<\/li><li><code>observe_auth_options_update<\/code>: Merge allowed external-auth options into the logon context for templates and handlers.<\/li><li><code>observe_auth_validated<\/code>: Match validated external identities to local users and trigger signup or logon continuation.<\/li><li><code>observe_logon_options<\/code>: Normalize and enrich logon options before authentication starts.<\/li><li><code>observe_logon_submit<\/code>: Check username\/password against the identity tables using <code>m_identity:check_username_pw<\/code>.<\/li><li><code>observe_m_config_update<\/code>: Flush the <code>auth_secret<\/code> depcache key when <code>mod_authentication.auth_secret<\/code> changes, and flush the <code>auth_anon_secret<\/code> depcache key when <code>mod_authentication.auth_anon_secret<\/code> changes.<\/li><li><code>observe_request_context<\/code>: Check for authentication cookies in the request using <code>z_context:get<\/code>.<\/li><li><code>observe_tick_1h<\/code>: Remove stale authentication and logon-history records in hourly maintenance.<\/li><\/ul>\n<p>Delegate callbacks:<\/p>\n<ul><li><code>event\/2<\/code> with <code>postback<\/code> messages: <code>close_all_sessions<\/code>.<\/li><li><code>event\/2<\/code> with <code>submit<\/code> messages: <code>signup_confirm<\/code>.<\/li><\/ul>","slug":"mod_authentication","doc_module_config":[{"default":"8","description":"The minimum length of new passwords.","has_default":true,"key":"password_min_length","module":"mod_authentication","type":"integer"},{"default":"true","description":"If true, users will have to confirm their signup by clicking on a link in an email.","has_default":true,"key":"is_signup_confirm","module":"mod_authentication","type":"boolean"},{"default":"172800","description":"The maximum age of a password reset token in seconds. Default is 2 days (172800 seconds).","has_default":true,"key":"reset_token_max_age","module":"mod_authentication","type":"integer"},{"default":"false","description":"If true, the user must enter both their username and password at once. Otherwise they are entered one by one, which helps checking other (external) login options.","has_default":true,"key":"is_one_step_logon","module":"mod_authentication","type":"boolean"},{"default":"false","description":"If true, the &#39;remember me&#39; option on the login form will be pre-checked. This will set a cookie that will automatically log them in when they return to the site.","has_default":true,"key":"is_rememberme","module":"mod_authentication","type":"boolean"},{"default":"false","description":"If true, on a password reset with a unregistered email address, an email is sent to that address with the message that it is unknown.","has_default":true,"key":"email_reminder_if_nomatch","module":"mod_authentication","type":"boolean"},{"default":"false","description":"If true, the password leak check with haveibeenpwned.com is disabled. This is useful for testing purposes, but must not be used in production.","has_default":true,"key":"password_disable_leak_check","module":"mod_authentication","type":"boolean"},{"default":"[]","description":"The site authentication key is used to encrypt the tokens that can be exchanged for a valid authentication cookie or MQTT login. It is automatically set, and must be a random string that is kept secret.","has_default":true,"key":"site_auth_key","module":"mod_authentication","type":"string"},{"default":"[]","description":"The site authentication secret is used to encrypt the authentication cookies. This key is used for sites without database connections, if there is a database connection then every user will receive their own key. It is automatically set, and must be a random string that is kept secret.","has_default":true,"key":"auth_secret","module":"mod_authentication","type":"string"},{"default":"[]","description":"The authentication user secret is placed in the encrypted authentication cookies. This secret is used for sites without database connections, if there is a database connection then every user will receive their own secret. It is automatically set, and must be a random string that is kept secret.","has_default":true,"key":"auth_user_secret","module":"mod_authentication","type":"string"},{"default":"[]","description":"The authentication secret for anonymous users is placed in the encrypted authentication cookies. This is used to authenticate anonymous users only, the auth_user_secret is used for authenticated users. It is automatically set, and must be a random string that is kept secret.","has_default":true,"key":"auth_anon_secret","module":"mod_authentication","type":"string"},{"default":"[]","description":"The secret used to sign the autologon cookie for automatic authentication of users that checked &#39;remember me&#39;. It is automatically set, and must be a random string that is kept secret.","has_default":true,"key":"auth_autologon_secret","module":"mod_authentication","type":"string"}],"is_protected":false,"visible_for":0,"tz":"UTC","language":["en"],"doc_source_hash":"f77d20d91c9e994ad68d709c6ade65a6b9e3347c7768bff282557c7c0276b3ed","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"},"category_id":{"id":320,"is_a":["meta","category"],"name":"module","title":"Modules","uri":"https:\/\/test.zotonic.com\/id\/320"},"doc_source_path":"apps\/zotonic_mod_authentication\/src\/mod_authentication.erl","publication_start":"2023-01-30T19:23:58Z","github_url":"https:\/\/github.com\/zotonic\/zotonic\/blob\/master\/apps\/zotonic_mod_authentication\/src\/mod_authentication.erl","pivot_location_lng":null,"doc_source_kind":"module","name":"doc_module_mod_authentication","is_unfindable":false,"is_published":true,"pivot_geocode":null,"created":"2020-05-30T05:47:18Z","uri":null,"doc_status":"current","is_dependent":false,"erlang_app":"zotonic_mod_authentication","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":"c34f80c7ab6700e5d77ac5730deaae0e4710e159\n","creator_id":{"id":336,"is_a":["person","robot"],"name":"gitbot","title":"Git","uri":"https:\/\/zotonic.com\/id\/336"},"modified":"2026-10-19T13:18:15Z","title_slug":"mod_authentication"},"uri":"https:\/\/zotonic.com\/id\/1306","uri_template":"https:\/\/zotonic.com\/id\/:id","websub":{"hub":"https:\/\/zotonic.com\/.zotonic\/websub","topic":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/1306"}},"status":"ok"}