<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Authentication on backd</title><link>https://fernandezvara.github.io/backd/docs/auth/</link><description>Recent content in Authentication on backd</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://fernandezvara.github.io/backd/docs/auth/index.xml" rel="self" type="application/rss+xml"/><item><title>Command-line administration</title><link>https://fernandezvara.github.io/backd/docs/auth/cli/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/auth/cli/</guid><description>&lt;p&gt;The &lt;code&gt;backd&lt;/code&gt; binary is also the command-line client for administering a realm. &lt;code&gt;backd user&lt;/code&gt; and &lt;code&gt;backd apikey&lt;/code&gt; don&amp;rsquo;t touch MongoDB: they call the realm&amp;rsquo;s &lt;a href="../admin/"&gt;admin API&lt;/a&gt; on a running &lt;code&gt;backd&lt;/code&gt;, as an administrator. They never need database credentials, and every change they make goes through the same checks as any other admin request, including &lt;a href="../../configuration/realm/#network-restrictions"&gt;network restrictions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Two commands write to MongoDB directly instead: &lt;code&gt;backd bootstrap&lt;/code&gt;, which creates a realm&amp;rsquo;s first administrator, and &lt;code&gt;backd secret rotate-key&lt;/code&gt;, which re-encrypts every realm&amp;rsquo;s &lt;a href="../../functions/secrets/"&gt;secrets&lt;/a&gt; under a new master key (see &lt;a href="../admin/#secrets"&gt;Secrets&lt;/a&gt;).&lt;/p&gt;</description></item><item><title>Users and passwords</title><link>https://fernandezvara.github.io/backd/docs/auth/users/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/auth/users/</guid><description>&lt;p&gt;The &lt;code&gt;backd user&lt;/code&gt; commands manage the users of a realm with &lt;code&gt;auth: enabled&lt;/code&gt;. They call the realm&amp;rsquo;s &lt;a href="../admin/"&gt;admin API&lt;/a&gt; on a running &lt;code&gt;backd&lt;/code&gt;, so you first &lt;a href="../cli/#logging-in"&gt;log in&lt;/a&gt; as an administrator (or set &lt;code&gt;BACKD_API_KEY&lt;/code&gt; to an admin API key). The realm&amp;rsquo;s first administrator is created with &lt;a href="../cli/#the-first-administrator"&gt;&lt;code&gt;backd bootstrap&lt;/code&gt;&lt;/a&gt;. Server-side services can call the admin API directly.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;backd login --realm blog --url https://api.example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;backd user list --realm blog
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Every command also takes &lt;code&gt;--url&lt;/code&gt;, to pick the server for that command.&lt;/p&gt;</description></item><item><title>Sign-up, login and sessions</title><link>https://fernandezvara.github.io/backd/docs/auth/sessions/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/auth/sessions/</guid><description>&lt;p&gt;What a signed-in user may do with data is decided by each collection&amp;rsquo;s &lt;a href="../rules/"&gt;access rules&lt;/a&gt;. Server-side services use &lt;a href="../api-keys/"&gt;API keys&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;Every realm with &lt;code&gt;auth: enabled&lt;/code&gt; has its authentication endpoints under &lt;code&gt;/v1/{realm}/_auth&lt;/code&gt;. A realm that doesn&amp;rsquo;t exist or has &lt;code&gt;auth: disabled&lt;/code&gt; answers &lt;code&gt;404 not_found&lt;/code&gt; on all of them.&lt;/p&gt;
&lt;h2 id="sessions-and-tokens"&gt;Sessions and tokens&lt;a class="hd-anchor" href="#sessions-and-tokens" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Signing up or logging in returns a &lt;strong&gt;session token&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;token&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;bds_mxamh1_afbN3BMzfXqDWhxYpXKF58FhWQ4r9eaLc9ew&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;token_type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Bearer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;session_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dars2ql90v6000bbohr0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;expires_at&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2026-10-26T12:58:18.988Z&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dars2ql90v600434mf0g&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;email&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ada@example.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;email_verified&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;roles&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;locale&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;created_at&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2026-09-26T12:58:18.838Z&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Send it on every request that needs a signed-in user:&lt;/p&gt;</description></item><item><title>API keys</title><link>https://fernandezvara.github.io/backd/docs/auth/api-keys/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/auth/api-keys/</guid><description>&lt;p&gt;API keys let server-side services (a backend, a worker, a script) call a realm&amp;rsquo;s data routes. A key belongs to one realm and gives &lt;strong&gt;full access to all of that realm&amp;rsquo;s data&lt;/strong&gt;, in every database.
&lt;aside class="hd-hint hd-hint--danger"&gt;
 &lt;p class="hd-hint-title"&gt;&lt;svg class="hd-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;circle cx="12" cy="12" r="9"/&gt;&lt;path d="m9 9 6 6M15 9l-6 6"/&gt;&lt;/svg&gt;
Danger&lt;/p&gt;
 A key is a password with no user behind it: it bypasses every &lt;a href="../rules/"&gt;access rule&lt;/a&gt;. &lt;strong&gt;Never ship one to a browser or a mobile app&lt;/strong&gt;, where every visitor can read it. Use it only from servers you control, keep it in a secret store, and give it an expiry.
&lt;/aside&gt;
&lt;/p&gt;</description></item><item><title>Access rules (rules:)</title><link>https://fernandezvara.github.io/backd/docs/auth/rules/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/auth/rules/</guid><description>&lt;p&gt;Each collection of a realm with &lt;code&gt;auth: enabled&lt;/code&gt; can have a &lt;code&gt;rules:&lt;/code&gt; section in its &lt;code&gt;collection.yaml&lt;/code&gt;, next to its &lt;code&gt;schema.json&lt;/code&gt;. Rules decide, per operation, whether a caller may act on a &lt;strong&gt;whole document&lt;/strong&gt;. There are no per-field permissions: data that needs different visibility belongs in a separate collection with its own rules.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$CONFIG_DIR/&amp;lt;realm&amp;gt;/&amp;lt;database&amp;gt;/&amp;lt;collection&amp;gt;/
 schema.json
 indexes.json # optional
 collection.yaml # optional — its `rules:` section is the access rules
 rules.test.yaml # optional — tests for the rules
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The same file holds the collection&amp;rsquo;s other policy: &lt;a href="../../files/file-fields/"&gt;&lt;code&gt;files:&lt;/code&gt;&lt;/a&gt;, &lt;code&gt;soft_delete:&lt;/code&gt; and &lt;code&gt;on_owner_delete:&lt;/code&gt; (see &lt;a href="../../configuration/config-dir/#collectionyaml"&gt;the collection file&lt;/a&gt;). This page is about the &lt;code&gt;rules:&lt;/code&gt; key.&lt;/p&gt;</description></item><item><title>Admin API</title><link>https://fernandezvara.github.io/backd/docs/auth/admin/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/auth/admin/</guid><description>&lt;p&gt;The admin API manages the users and API keys of a realm. &lt;a href="../users/"&gt;&lt;code&gt;backd user&lt;/code&gt;&lt;/a&gt; and &lt;a href="../api-keys/"&gt;&lt;code&gt;backd apikey&lt;/code&gt;&lt;/a&gt; are command-line clients of it (see &lt;a href="../cli/"&gt;Command-line administration&lt;/a&gt;), and server-side services can call it directly. It lives under &lt;code&gt;/v1/{realm}/_admin&lt;/code&gt; in every realm with &lt;code&gt;auth: enabled&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Every request needs one of the realm&amp;rsquo;s &lt;a href="../api-keys/"&gt;API keys&lt;/a&gt; with the &lt;code&gt;admin&lt;/code&gt; role, acting as itself, or the session of a user holding one of the realm&amp;rsquo;s &lt;a href="../../configuration/realm/#roles"&gt;admin roles&lt;/a&gt;:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Credential&lt;/th&gt;
 &lt;th&gt;Answer&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;API key with the &lt;code&gt;admin&lt;/code&gt; role&lt;/td&gt;
 &lt;td&gt;Allowed&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Session of a user holding an admin role (&lt;code&gt;admin: true&lt;/code&gt; in &lt;code&gt;realm.yaml&lt;/code&gt;)&lt;/td&gt;
 &lt;td&gt;Allowed&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Session of a user whose admin role opens only some &lt;a href="#admin-rights"&gt;areas&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;Allowed for those areas; &lt;code&gt;403 forbidden&lt;/code&gt; naming the missing one for the rest&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;API key with the &lt;code&gt;data&lt;/code&gt; role&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;403 forbidden&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;None, or an invalid key&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;401 unauthenticated&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Session of a user without an admin role&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;403 forbidden&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;X-Backd-On-Behalf-Of&lt;/code&gt; with any credential&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;400 invalid_header&lt;/code&gt;: admin calls never act as another user&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;aside class="hd-hint hd-hint--danger"&gt;
 &lt;p class="hd-hint-title"&gt;&lt;svg class="hd-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;circle cx="12" cy="12" r="9"/&gt;&lt;path d="m9 9 6 6M15 9l-6 6"/&gt;&lt;/svg&gt;
Danger&lt;/p&gt;</description></item><item><title>Admin UI</title><link>https://fernandezvara.github.io/backd/docs/auth/admin-ui/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/auth/admin-ui/</guid><description>&lt;p&gt;The admin UI is a web interface for realm administrators and developers. It is a client of the &lt;a href="../admin/"&gt;Admin API&lt;/a&gt; and nothing more: it can do nothing the CLI can&amp;rsquo;t, and every call it makes is authenticated, network-checked and audited by the server like any other. This page is the start of its guide; each area of the interface (users, keys, secrets, audit, functions, data, configuration) is added to it as the area ships.&lt;/p&gt;</description></item><item><title>Audit trail</title><link>https://fernandezvara.github.io/backd/docs/auth/audit/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/auth/audit/</guid><description>&lt;p&gt;Each realm with &lt;code&gt;auth: enabled&lt;/code&gt; keeps an &lt;strong&gt;audit trail&lt;/strong&gt;: one record per security-sensitive action or event, with who did it, to what, when and from where. It answers questions such as &amp;ldquo;who gave Bob the admin role?&amp;rdquo; or &amp;ldquo;which key created this user?&amp;rdquo;. Records can be read, but not changed or deleted: they expire after the realm&amp;rsquo;s retention period.&lt;/p&gt;
&lt;h2 id="what-is-recorded"&gt;What is recorded&lt;a class="hd-anchor" href="#what-is-recorded" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Action&lt;/th&gt;
 &lt;th&gt;When&lt;/th&gt;
 &lt;th&gt;Details&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.create&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator (or &lt;code&gt;backd bootstrap&lt;/code&gt;) creates a user&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;password&lt;/code&gt; (whether one was set), &lt;code&gt;roles&lt;/code&gt; (seeded from &lt;code&gt;realm.yaml&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.signup&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A user signs up&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;invited&lt;/code&gt;, &lt;code&gt;roles&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.password&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator sets a user&amp;rsquo;s password&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.password_change&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A user changes their own password&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.verify_email&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator marks an email as verified, or not; or a user verifies it with the link in their email&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;verified&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.password_reset&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A user sets a new password with a reset link&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;verified_address&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.email_changed&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A user&amp;rsquo;s address changes: confirmed by the new address, or set by an administrator&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;by&lt;/code&gt; (&lt;code&gt;self&lt;/code&gt; or &lt;code&gt;admin&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.email_change_reverted&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;The old address undid a change&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.purged_unverified&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A worker deletes accounts that never verified their address&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;count&lt;/code&gt;, &lt;code&gt;older_than&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;function.invoke_manual&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator runs a function by hand (&lt;a href="../admin/"&gt;admin API&lt;/a&gt;)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;as&lt;/code&gt; (the user&amp;rsquo;s &lt;strong&gt;id&lt;/strong&gt;, never their email, or null)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;files.versions.regenerate&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator runs &lt;a href="../../files/file-fields/#after-you-change-a-declaration"&gt;&lt;code&gt;backd files regenerate&lt;/code&gt;&lt;/a&gt; (&lt;a href="../admin/"&gt;admin API&lt;/a&gt;)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;version&lt;/code&gt;, &lt;code&gt;missing_only&lt;/code&gt;, &lt;code&gt;job_id&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;storage.reconcile&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator runs &lt;a href="../../files/maintenance/#reconciling"&gt;&lt;code&gt;backd storage reconcile&lt;/code&gt;&lt;/a&gt; (&lt;a href="../admin/"&gt;admin API&lt;/a&gt;)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;delete&lt;/code&gt;, &lt;code&gt;orphans&lt;/code&gt; (how many were found), &lt;code&gt;deleted&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;storage.check&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator runs a &lt;a href="../../files/storage/#checking-it"&gt;storage check&lt;/a&gt; (&lt;a href="../admin/"&gt;admin API&lt;/a&gt;); never the keys or anything stored&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ok&lt;/code&gt;, &lt;code&gt;provider&lt;/code&gt;, &lt;code&gt;bucket&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;data.check&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator starts a &lt;a href="../../configuration/validation/#finding-documents-that-no-longer-match"&gt;schema check&lt;/a&gt; (&lt;a href="../admin/"&gt;admin API&lt;/a&gt;); the target is &lt;code&gt;data:&amp;lt;database&amp;gt;/&amp;lt;collection&amp;gt;&lt;/code&gt;, &lt;code&gt;data:&amp;lt;database&amp;gt;&lt;/code&gt; or &lt;code&gt;data:*&lt;/code&gt;; never the report&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;collections&lt;/code&gt;, &lt;code&gt;limit&lt;/code&gt;, &lt;code&gt;job_id&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;schedule.pause&lt;/code&gt;, &lt;code&gt;schedule.resume&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator pauses or resumes a function&amp;rsquo;s schedule (&lt;a href="../admin/"&gt;admin API&lt;/a&gt;); only a change is recorded; the target is &lt;code&gt;schedule:&amp;lt;database&amp;gt;/&amp;lt;function&amp;gt;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;none&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;job.cancel&lt;/code&gt;, &lt;code&gt;job.rerun&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator cancels a job, or queues a finished one again (&lt;a href="../admin/"&gt;admin API&lt;/a&gt;); the target is &lt;code&gt;job:&amp;lt;id&amp;gt;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;function&lt;/code&gt;; for a re-run also &lt;code&gt;new_job&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.disable&lt;/code&gt;, &lt;code&gt;user.enable&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator disables or re-enables a user&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.delete&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator erases a user (the tombstone is made; the data work is in the job)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;job_id&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.erased&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;The erase job finished, or failed for good&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;job_id&lt;/code&gt; and &lt;code&gt;counts&lt;/code&gt; per &lt;code&gt;database/collection/operation&lt;/code&gt;; &lt;code&gt;needs_attention&lt;/code&gt; and &lt;code&gt;error&lt;/code&gt; when it failed. Never content&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.delete_account&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A user deletes their own account (it is deactivated, not erased)&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;user.networks&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A user&amp;rsquo;s &lt;a href="../../configuration/realm/#network-restrictions"&gt;network restrictions&lt;/a&gt; change, through the API or from &lt;code&gt;realm.yaml&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;admin_networks&lt;/code&gt;, &lt;code&gt;login_networks&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;role.add&lt;/code&gt;, &lt;code&gt;role.remove&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A role is assigned or taken away, through the API or from &lt;code&gt;realm.yaml&lt;/code&gt; seeds&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;role&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;apikey.create&lt;/code&gt;, &lt;code&gt;apikey.revoke&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An API key is created or revoked&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;role&lt;/code&gt;, &lt;code&gt;networks&lt;/code&gt;, &lt;code&gt;expires_at&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;invitation.create&lt;/code&gt;, &lt;code&gt;invitation.revoke&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An invitation is created or revoked&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;bound_to_email&lt;/code&gt; (whether it is), &lt;code&gt;expires_at&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;invitation.sent&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An invitation is emailed to its address&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;expires_at&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;admin.login&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A user holding an admin role logs in&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;session_id&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;data.create&lt;/code&gt;, &lt;code&gt;data.update&lt;/code&gt;, &lt;code&gt;data.delete&lt;/code&gt;, &lt;code&gt;data.restore&lt;/code&gt;, &lt;code&gt;data.purge&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;A document is written through the &lt;a href="../admin/#data"&gt;admin data route&lt;/a&gt; (a batch audits each operation)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;database&lt;/code&gt;, &lt;code&gt;collection&lt;/code&gt;, &lt;code&gt;id&lt;/code&gt;; the target is &lt;code&gt;doc:&amp;lt;database&amp;gt;/&amp;lt;collection&amp;gt;/&amp;lt;id&amp;gt;&lt;/code&gt;; never content&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;session.revoke&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An administrator ends a user&amp;rsquo;s session (&lt;a href="../admin/"&gt;admin API&lt;/a&gt;)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;session&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;admin.refused&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;An admin API request is refused: by a network restriction, or because the administrator&amp;rsquo;s roles don&amp;rsquo;t open the &lt;a href="../admin/#admin-rights"&gt;area&lt;/a&gt; or hold the rights of the user or role involved&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;reason&lt;/code&gt;, &lt;code&gt;method&lt;/code&gt;, &lt;code&gt;path&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;realm.bootstrap&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;backd bootstrap&lt;/code&gt; creates the realm&amp;rsquo;s first administrator&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;role&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Failed logins aren&amp;rsquo;t recorded here: they are &lt;a href="../sessions/#brute-force-protection"&gt;throttled&lt;/a&gt; and counted, and every request is in the access log.&lt;/p&gt;</description></item><item><title>Deleting and erasing users</title><link>https://fernandezvara.github.io/backd/docs/auth/erasure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/auth/erasure/</guid><description>&lt;p&gt;&lt;code&gt;backd&lt;/code&gt; separates two things people call &amp;ldquo;deleting an account&amp;rdquo;:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;What&lt;/th&gt;
 &lt;th&gt;Who&lt;/th&gt;
 &lt;th&gt;Effect&lt;/th&gt;
 &lt;th&gt;Reversible&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Deactivate&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;the user (&lt;code&gt;DELETE /_auth/me&lt;/code&gt;, with their password), or an administrator (&lt;code&gt;PATCH /_admin/users/{id}&lt;/code&gt; with &lt;code&gt;disabled&lt;/code&gt;, &lt;code&gt;backd user disable&lt;/code&gt;)&lt;/td&gt;
 &lt;td&gt;the user is disabled and every session ends; &lt;strong&gt;all data is kept&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;yes: an administrator reactivates (&lt;code&gt;backd user enable&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Erase&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;an administrator (&lt;code&gt;DELETE /_admin/users/{id}&lt;/code&gt;, &lt;code&gt;backd user delete --yes&lt;/code&gt;)&lt;/td&gt;
 &lt;td&gt;the user becomes a tombstone, and the policies of your collections are applied (below)&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;no&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;aside class="hd-hint hd-hint--note"&gt;
 &lt;p class="hd-hint-title"&gt;&lt;svg class="hd-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;circle cx="12" cy="12" r="9"/&gt;&lt;path d="M12 16v-4m0-4h.01"/&gt;&lt;/svg&gt;
Note&lt;/p&gt;</description></item><item><title>Security model</title><link>https://fernandezvara.github.io/backd/docs/auth/security/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/auth/security/</guid><description>&lt;p&gt;This page summarizes how &lt;code&gt;backd&lt;/code&gt; protects data in realms with &lt;code&gt;auth: enabled&lt;/code&gt;, and what the operator is responsible for. To report a vulnerability, see &lt;a href="https://github.com/fernandezvara/backd/blob/main/SECURITY.md"&gt;&lt;code&gt;SECURITY.md&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="who-can-do-what"&gt;Who can do what&lt;a class="hd-anchor" href="#who-can-do-what" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Caller&lt;/th&gt;
 &lt;th&gt;Proves identity with&lt;/th&gt;
 &lt;th&gt;Can&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Anonymous&lt;/td&gt;
 &lt;td&gt;nothing&lt;/td&gt;
 &lt;td&gt;What &lt;a href="../rules/"&gt;access rules&lt;/a&gt; allow &lt;code&gt;user == nil&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;User&lt;/td&gt;
 &lt;td&gt;session token (&lt;code&gt;bds_…&lt;/code&gt;)&lt;/td&gt;
 &lt;td&gt;What access rules allow that user; manage their own account and sessions&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Server-side service&lt;/td&gt;
 &lt;td&gt;API key (&lt;code&gt;bdk_…&lt;/code&gt;) with the &lt;code&gt;data&lt;/code&gt; role&lt;/td&gt;
 &lt;td&gt;Everything in the realm&amp;rsquo;s data; act as a user with &lt;code&gt;X-Backd-On-Behalf-Of&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Management tooling&lt;/td&gt;
 &lt;td&gt;API key with the &lt;code&gt;admin&lt;/code&gt; role&lt;/td&gt;
 &lt;td&gt;The same, plus the &lt;a href="../admin/"&gt;admin API&lt;/a&gt;: users, roles, invitations, API keys&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Administrator&lt;/td&gt;
 &lt;td&gt;session of a user holding an &lt;a href="../../configuration/realm/#roles"&gt;admin role&lt;/a&gt;, for example through &lt;a href="../cli/"&gt;&lt;code&gt;backd login&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;What access rules allow that user, plus the admin API&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Operator&lt;/td&gt;
 &lt;td&gt;access to &lt;code&gt;CONFIG_DIR&lt;/code&gt; and MongoDB&lt;/td&gt;
 &lt;td&gt;Everything, including creating a realm&amp;rsquo;s first administrator with &lt;a href="../cli/#the-first-administrator"&gt;&lt;code&gt;backd bootstrap&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Credentials belong to one realm and are unknown in every other realm. Invalid, expired or revoked credentials are always refused (&lt;code&gt;401&lt;/code&gt;), never downgraded to anonymous access.&lt;/p&gt;</description></item></channel></rss>