{"result":{"depiction_url":null,"edges":{"in_module":{"objects":[{"created":"2026-09-30T09:18:26Z","object_id":{"id":1306,"is_a":["text","documentation","reference","module"],"name":"doc_module_mod_authentication","title":"mod_authentication","uri":"https:\/\/zotonic.com\/id\/1306"},"seq":1}],"predicate":{"id":333,"is_a":["meta","predicate"],"name":"in_module","title":{"_type":"trans","tr":{"en":"In module"}},"uri":"https:\/\/zotonic.com\/id\/in_module"}},"refers":{"objects":[{"created":"2026-09-30T09:32:49Z","object_id":{"id":2741,"is_a":["text","documentation","reference","cotonic_reference","cotonic_model"],"name":"doc_cotonic_model_localstorage","title":"model\/localStorage","uri":"https:\/\/zotonic.com\/id\/2741"},"seq":1000000},{"created":"2026-09-30T09:32:49Z","object_id":{"id":2742,"is_a":["text","documentation","reference","cotonic_reference","cotonic_model"],"name":"doc_cotonic_model_sessionstorage","title":"model\/sessionStorage","uri":"https:\/\/zotonic.com\/id\/2742"},"seq":1000000},{"created":"2026-09-30T09:32:49Z","object_id":{"id":2743,"is_a":["text","documentation","reference","cotonic_reference","cotonic_model"],"name":"doc_cotonic_model_sessionid","title":"model\/sessionId","uri":"https:\/\/zotonic.com\/id\/2743"},"seq":1000000}],"predicate":{"id":2409,"is_a":["meta","predicate"],"name":"refers","title":{"_type":"trans","tr":{"en":"Refers"}},"uri":"https:\/\/zotonic.com\/id\/refers"}},"subject":{"objects":[{"created":"2026-09-30T09:18:26Z","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-30T09:18:26Z","object_id":{"id":2563,"is_a":["categorization","keyword","keyword_audience"],"name":"zotonic_topic_frontend_developer","title":"Frontend developer","uri":"https:\/\/zotonic.com\/id\/2563"},"seq":2},{"created":"2026-09-30T09:18:26Z","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-30T09:18:26Z","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-30T09:18:26Z","object_id":{"id":2625,"is_a":["categorization","keyword","keyword_architecture"],"name":"zotonic_topic_model","title":"Model","uri":"https:\/\/zotonic.com\/id\/2625"},"seq":5},{"created":"2026-09-30T09:18:26Z","object_id":{"id":2673,"is_a":["categorization","keyword","keyword_technology"],"name":"zotonic_topic_javascript","title":"JavaScript","uri":"https:\/\/zotonic.com\/id\/2673"},"seq":6},{"created":"2026-09-30T09:18:26Z","object_id":{"id":2718,"is_a":["categorization","keyword","keyword_technology"],"name":"zotonic_topic_cotonic","title":"Cotonic","uri":"https:\/\/zotonic.com\/id\/2718"},"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":2754,"is_a":["text","documentation","reference","cotonic_reference","cotonic_model"],"links":[{"rel":"self","target":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/2754"},{"rel":"hub","target":"https:\/\/zotonic.com\/.zotonic\/websub"}],"medium":null,"medium_url":null,"name":"doc_zotonic_cotonic_model_auth","page_url":{"en":"https:\/\/zotonic.com\/cotonic\/zotonic-models\/auth","x-default":"https:\/\/zotonic.com\/cotonic\/zotonic-models\/auth"},"preview_url":null,"resource":{"version":22,"pivot_location_lat":null,"title":"model\/auth","is_authoritative":true,"body":"<h1>model\/auth<\/h1>\n<p>Owns browser authentication state and communicates with <code>\/zotonic-auth<\/code>.\nIt checks and refreshes authentication, manages login\/logout and password\noperations, and synchronizes with other tabs. Use the authentication worker\nloaded by Zotonic&#39;s normal page setup.<\/p>\n<h2>Commands<\/h2>\n<p>All topics below start with <code>model\/auth\/<\/code>. Unless stated otherwise, use\n<code>publish<\/code> and observe the events below; commands do not return a direct reply.<\/p>\n<table class=\"table\"><thead><tr><th>Topic suffix<\/th><th>Payload and behavior<\/th><\/tr><\/thead><tbody><tr><td><code>post\/check<\/code><\/td><td>Recheck authentication; payload is ignored.<\/td><\/tr><tr><td><code>post\/refresh<\/code><\/td><td>Refresh authentication, passing the payload as refresh options.<\/td><\/tr><tr><td><code>post\/logon<\/code><\/td><td><code>username<\/code>, <code>password<\/code>, optional <code>passcode<\/code>, <code>rememberme<\/code>, <code>code-new<\/code>, and <code>test_passcode<\/code>.<\/td><\/tr><tr><td><code>post\/form\/logon<\/code><\/td><td>Cotonic form payload: credentials under <code>value<\/code>; <code>message.username<\/code> overrides <code>value.username<\/code> when non-empty. Also accepts <code>value.is_username_check<\/code>, <code>value.authuser<\/code>, and <code>value.onauth<\/code>.<\/td><\/tr><tr><td><code>post\/logoff<\/code><\/td><td>Log out; payload is ignored.<\/td><\/tr><tr><td><code>post\/switch-user<\/code><\/td><td><code>{ user_id: ... }<\/code>; the server determines whether the switch is authorized.<\/td><\/tr><tr><td><code>post\/onetime-token<\/code><\/td><td><code>{ token: ..., url: ... }<\/code> for an authentication handoff.<\/td><\/tr><tr><td><code>post\/reset-code-check<\/code><\/td><td><code>username<\/code>, <code>secret<\/code>, and optional <code>passcode<\/code>. Supports a response topic and returns the server&#39;s reset-check response.<\/td><\/tr><tr><td><code>post\/reset<\/code><\/td><td><code>username<\/code>, <code>secret<\/code>, new <code>password<\/code>, optional <code>passcode<\/code>, <code>rememberme<\/code>, <code>onauth<\/code>, <code>code-new<\/code>, and <code>test_passcode<\/code>.<\/td><\/tr><tr><td><code>post\/change<\/code><\/td><td>Current <code>password<\/code>, new <code>password_reset<\/code>, optional <code>passcode<\/code>, <code>onauth<\/code>, <code>code-new<\/code>, and <code>test_passcode<\/code>.<\/td><\/tr><\/tbody><\/table>\n<pre class=\"notranslate\"><code class=\"notranslate language-javascript\">cotonic.broker.publish(&quot;model\/auth\/post\/check&quot;, {});\n<\/code><\/pre>\n<p>Only the reset-code check explicitly supports a direct call:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-javascript\">cotonic.broker.call(&quot;model\/auth\/post\/reset-code-check&quot;, {\n    username: &quot;reader&quot;,\n    secret: resetSecret\n}).then(function(msg) {\n    console.log(&quot;Reset check:&quot;, msg.payload);\n});\n<\/code><\/pre>\n<p>A fetch failure for that operation replies with\n<code>{ result: &quot;error&quot;, error: &quot;fetch&quot; }<\/code>.<\/p>\n<h2>Events<\/h2>\n<p>All event topics start with <code>model\/auth\/<\/code>.<\/p>\n<table class=\"table\"><thead><tr><th>Topic suffix<\/th><th>Payload<\/th><th>Retained<\/th><\/tr><\/thead><tbody><tr><td><code>event\/auth<\/code><\/td><td>Authentication state, including <code>status<\/code>, <code>is_authenticated<\/code>, <code>user_id<\/code>, <code>username<\/code>, and <code>preferences<\/code>.<\/td><td>Yes<\/td><\/tr><tr><td><code>event\/auth-user-id<\/code><\/td><td>Current user ID when the worker enters its known-authentication state.<\/td><td>No<\/td><\/tr><tr><td><code>event\/auth-changing<\/code><\/td><td><code>{ onauth, auth }<\/code> during an authentication transition.<\/td><td>No<\/td><\/tr><tr><td><code>event\/auth-error<\/code><\/td><td><code>{ error, data }<\/code>.<\/td><td>No<\/td><\/tr><tr><td><code>event\/auth-change-result<\/code><\/td><td>Server result of a password-change request.<\/td><td>No<\/td><\/tr><tr><td><code>event\/ui-status<\/code><\/td><td><code>{ classes, status: { auth: &quot;user&quot; or &quot;anonymous&quot; } }<\/code>.<\/td><td>No<\/td><\/tr><tr><td><code>event\/ping<\/code><\/td><td><code>&quot;pong&quot;<\/code> after subscriptions are installed.<\/td><td>Yes<\/td><\/tr><\/tbody><\/table>\n<pre class=\"notranslate\"><code class=\"notranslate language-javascript\">cotonic.broker.subscribe(&quot;model\/auth\/event\/auth&quot;, function(msg) {\n    const auth = msg.payload;\n    console.log(&quot;Authenticated:&quot;, auth.is_authenticated);\n});\n<\/code><\/pre>\n<p>The worker listens to <code>model\/ui\/event\/recent-activity<\/code> for keep-alive decisions,\n<code>model\/sessionStorage\/event\/auth-user-id<\/code> for user changes, and\n<code>model\/serviceWorker\/event\/broadcast\/auth-sync<\/code> for cross-tab checks. Its\nadvertised dependencies are <a href=\"\/id\/doc_cotonic_model_sessionstorage\" class=\"doc-reference doc-reference-cotonic\"><code>cotonic#sessionStorage<\/code><\/a>, <a href=\"\/id\/doc_cotonic_model_localstorage\" class=\"doc-reference doc-reference-cotonic\"><code>cotonic#localStorage<\/code><\/a>, and\n<a href=\"\/id\/doc_cotonic_model_sessionid\" class=\"doc-reference doc-reference-cotonic\"><code>cotonic#sessionId<\/code><\/a>.<\/p>\n<p>Client state describes the interface&#39;s current view of authentication. Server\nmodels and actions still enforce their own access control.<\/p>\n<h2>Implementation<\/h2>\n<p><a href=\"https:\/\/github.com\/zotonic\/zotonic\/blob\/master\/apps\/zotonic_mod_authentication\/priv\/lib\/js\/zotonic.auth.worker.js\">JavaScript source<\/a>.<\/p>","slug":"model-auth","is_protected":false,"visible_for":0,"tz":"UTC","language":["en"],"doc_source_hash":"f507d938c17e62cba52a8f481b03d2304e01430c2148acaab54a9e4a36ae27e5","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":2723,"is_a":["meta","category"],"name":"cotonic_model","title":"Cotonic models","uri":"https:\/\/zotonic.com\/id\/cotonic_model"},"doc_source_path":"doc\/cotonic-models\/auth.md","publication_start":"2026-09-30T09:18:26Z","page_path":"\/cotonic\/zotonic-models\/auth","github_url":"https:\/\/github.com\/zotonic\/zotonic\/blob\/master\/doc\/cotonic-models\/auth.md","pivot_location_lng":null,"doc_source_kind":"cotonic_model","name":"doc_zotonic_cotonic_model_auth","is_unfindable":false,"is_published":true,"pivot_geocode":null,"created":"2026-09-30T09:18:26Z","uri":null,"doc_status":"current","is_dependent":false,"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":"b8c4b2ccdc223257f311968fbd17b2d66f0c4156\n","creator_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"modified":"2026-09-30T09:40:08Z","title_slug":"model-auth"},"uri":"https:\/\/zotonic.com\/id\/2754","uri_template":"https:\/\/zotonic.com\/id\/:id","websub":{"hub":"https:\/\/zotonic.com\/.zotonic\/websub","topic":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/2754"}},"status":"ok"}