<?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 back(d)</title><link>https://fernandezvara.github.io/backd/docs/build/auth/</link><description>Recent content in Authentication on back(d)</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://fernandezvara.github.io/backd/docs/build/auth/index.xml" rel="self" type="application/rss+xml"/><item><title>Users and passwords</title><link>https://fernandezvara.github.io/backd/docs/build/auth/users/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/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="../../../operate/administration/admin/"&gt;admin API&lt;/a&gt; on a running &lt;code&gt;backd&lt;/code&gt;, so you first &lt;a href="../../../operate/administration/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="../../../operate/administration/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/build/auth/sessions/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/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>Magic links</title><link>https://fernandezvara.github.io/backd/docs/build/auth/magic-links/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/auth/magic-links/</guid><description>&lt;p&gt;A &lt;strong&gt;magic link&lt;/strong&gt; signs a user in with nothing but their mailbox. The email carries &lt;strong&gt;a link&lt;/strong&gt; (opened on the device that asked) and &lt;strong&gt;a 6-digit code&lt;/strong&gt; (typed in the app that asked, on any device); either one works, once, for 10 minutes. It is one more first factor, next to a &lt;a href="../sessions/"&gt;password&lt;/a&gt; and &lt;a href="../providers/"&gt;providers&lt;/a&gt;: a user with a &lt;a href="../mfa/"&gt;second factor&lt;/a&gt; is still asked for it.&lt;/p&gt;
&lt;p&gt;It proves the same thing a &lt;a href="../sessions/#password-reset"&gt;password reset&lt;/a&gt; does (control of the mailbox), so it is as strong as that.&lt;/p&gt;</description></item><item><title>Re-authentication</title><link>https://fernandezvara.github.io/backd/docs/build/auth/reauth/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/auth/reauth/</guid><description>&lt;p&gt;A session proves who a request comes from &lt;strong&gt;when it started&lt;/strong&gt;, not that the person is still at the keyboard. Before an action that is hard to undo or that could lock the real user out, &lt;code&gt;backd&lt;/code&gt; asks for one &lt;strong&gt;fresh proof&lt;/strong&gt; of identity. It is the same single step for every kind of user, and it replaces the &lt;code&gt;password&lt;/code&gt; field that these endpoints used to take.&lt;/p&gt;
&lt;h2 id="the-proof"&gt;The proof&lt;a class="hd-anchor" href="#the-proof" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;POST /_auth/reauth&lt;/code&gt; takes the strongest proof the user has:&lt;/p&gt;</description></item><item><title>Multi-factor authentication</title><link>https://fernandezvara.github.io/backd/docs/build/auth/mfa/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/auth/mfa/</guid><description>&lt;p&gt;A realm can ask for a &lt;strong&gt;second factor&lt;/strong&gt; after the first one. The first factor is whatever the user used to say who they are: a password, a &lt;a href="../providers/"&gt;provider&lt;/a&gt; or a &lt;a href="../magic-links/"&gt;magic link&lt;/a&gt;. The second factor is a one-time code from an authenticator app, or one of ten recovery codes.&lt;/p&gt;
&lt;p&gt;The second step is built &lt;strong&gt;once&lt;/strong&gt; and shared by every first factor, so a user with MFA is asked for a code whether they signed in with a password or with Google.&lt;/p&gt;</description></item><item><title>Sign in with Google, Microsoft or Apple</title><link>https://fernandezvara.github.io/backd/docs/build/auth/providers/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/auth/providers/</guid><description>&lt;p&gt;A realm can let its users sign in with &lt;strong&gt;Google&lt;/strong&gt;, &lt;strong&gt;Microsoft&lt;/strong&gt; or &lt;strong&gt;Apple&lt;/strong&gt;. backd runs the redirect flow with the provider, checks the answer, finds or creates the user, and gives your app a one-time code to trade for a session. A user can have a password and any number of providers at once (at most one of each): they are &lt;a href="../sessions/#sign-in-methods"&gt;sign-in methods&lt;/a&gt; of the same user, so roles, rules and owned documents don&amp;rsquo;t depend on how the user signed in.&lt;/p&gt;</description></item><item><title>Access rules (rules:)</title><link>https://fernandezvara.github.io/backd/docs/build/auth/rules/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/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>Consents</title><link>https://fernandezvara.github.io/backd/docs/build/auth/consents/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/auth/consents/</guid><description>&lt;p&gt;Apps that handle personal data usually have to show people a text (terms, a privacy notice, marketing) and keep proof of what they accepted and when. &lt;code&gt;backd&lt;/code&gt; keeps the &lt;strong&gt;texts&lt;/strong&gt; with the rest of the configuration, serves them to apps, and records acceptances in an &lt;strong&gt;append-only&lt;/strong&gt; history.&lt;/p&gt;
&lt;aside class="hd-hint hd-hint--note"&gt;
 &lt;p class="hd-hint-title"&gt;&lt;i class="ph ph-note hd-icon" aria-hidden="true"&gt;&lt;/i&gt;
Note&lt;/p&gt;
 &lt;code&gt;backd&lt;/code&gt; provides the mechanisms. Which texts you need, on which legal basis and for how long you keep the records are decisions for you and your lawyers; nothing here is legal advice.
&lt;/aside&gt;

&lt;h2 id="declaring-consents"&gt;Declaring consents&lt;a class="hd-anchor" href="#declaring-consents" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;In &lt;code&gt;realm.yaml&lt;/code&gt;:&lt;/p&gt;</description></item><item><title>API keys</title><link>https://fernandezvara.github.io/backd/docs/build/auth/api-keys/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/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;i class="ph ph-x-circle hd-icon" aria-hidden="true"&gt;&lt;/i&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></channel></rss>