> ## Documentation Index
> Fetch the complete documentation index at: https://veriqa.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Sign-in from trusted networks

> Sign-ins to an internal application start only from your company's networks — the office and the VPN — so an outside attacker cannot start a sign-in and send its QR code to an employee to confirm.

A sign-in with a QR code can be forwarded: an attacker starts a sign-in in their own browser and
talks an employee into confirming it. An internal application — an intranet, a back office, an admin
panel — has no reason to accept sign-ins from outside the company. When a sign-in can start only from
the office network or over the VPN, an outside attacker has no QR code to forward. Employees still
confirm the sign-in in their messaging app, and the phone stays on mobile data. Neither Veriqa nor
your application changes: you set the restriction on the reverse proxy, and it works with the current
version.

## What you build yourself

1. **List your networks.** The office ranges and the VPN address pool, both IPv4 and IPv6. Include
   only networks where you control who gets in: a managed device, a VPN sign-in, a building pass.
2. **Restrict `/connect/authorize` on the proxy.** Only this route starts a sign-in. An NGINX example
   with documentation address ranges, to add alongside the configuration from
   [Behind a reverse proxy](https://veriqa.app/docs/guides/reverse-proxy.md#nginx):

   ```nginx theme={null}
   location ~* ^/connect/authorize/?$ {
       allow 203.0.113.0/24;    # office
       allow 198.51.100.0/24;   # VPN pool
       allow 2001:db8:10::/48;  # office, IPv6
       deny  all;

       proxy_pass http://127.0.0.1:8080;  # the same address as in location /
       # the other proxy_* directives as in location /
   }
   ```

   Veriqa accepts this route regardless of case and with a trailing slash, so the block matches it the
   same way: `~*` ignores case, and `/?` allows the slash. An exact `location =` would let
   `/CONNECT/AUTHORIZE` through the general `location /`. The query string does not affect the match.
   If Veriqa runs [under a path prefix](https://veriqa.app/docs/guides/reverse-proxy.md#under-a-path-prefix), include the prefix
   in the expression and let it repeat: `^(/auth/veriqa)+/connect/authorize/?$`. When your general block trims the
   prefix, `/auth/veriqa/auth/veriqa/connect/authorize` reaches Veriqa as
   `/auth/veriqa/connect/authorize`, and Veriqa still treats it as this route. NGINX checks
   regular expressions in the order they appear, so put this block before the other `location ~`
   blocks. Make sure no `location ^~` or `location =` block covers this path: NGINX then skips regular
   expressions.

   In this block `proxy_pass` forwards the path unchanged, because NGINX does not allow a URI in
   `proxy_pass` inside a regular-expression `location`. Veriqa still accepts the prefixed path even if
   your general block trims the prefix. Use the same address as your general block, for example the
   same `upstream`, so that these requests reach your instances the same way as all others.
3. **Leave the other routes open.** The phone opens the pages under `/auth/` and `/r/` over mobile
   data, the messaging platforms call the webhooks under `/api/channels/`, and your backend calls
   `/connect/token` from wherever it runs. The browser that has already passed the check opens
   the sign-in page and its WebSocket. The phone also uses the routes under
   `/connect/authorize/callback`, for example to submit the form that asks for a missing profile
   field, so do not restrict them. The block above does not match them.
4. **Check the client's address.** NGINX checks the address of whoever connects to it. If a
   load balancer or a CDN sits in front of NGINX, restore the client address from its header first
   with the `set_real_ip_from` and `real_ip_header` directives of the realip module; otherwise every
   request comes from the load balancer, and they all pass or all fail together. On the Veriqa side,
   configure trust in the proxy itself in the `ForwardedHeaders` section — see
   [self-hosted, step 6](https://veriqa.app/docs/quickstart/self-hosted.md#6-put-it-behind-a-reverse-proxy).
5. **Tell the person why.** Outside your networks the browser gets a 403. Serve your own page for that
   response (`error_page 403` in the same `location`) saying that sign-in works only from the office
   network or over the VPN.

## Why this works

A forwarded-QR-code attack starts when the attacker's own browser opens the sign-in page. From outside
your networks that browser gets a 403 instead of the page, and there is no QR code to send. To start a
sign-in, the attacker needs a device inside the network — the RFC puts it as "the attacker needs to
have access to a device on the network".

In BCP 247 terms, this is the Trusted Networks mitigation (RFC 10027 §6.1.8). The list lives in your proxy rather than
in Veriqa, which is why [Veriqa, BCP 247 and the threat model](https://veriqa.app/docs/concepts/cross-device-security.md) marks the row as not
covered in the core and points here for what you can do today. The same list of networks can also pick
the surface in the [Place and identity](https://veriqa.app/docs/scenarios/place-and-identity.md) scenario.

## What to keep in mind

* **The rule applies to every application on the instance.** They share the `/connect/authorize`
  route. The proxy can tell which application starts a sign-in only from the `client_id` query
  parameter, and the same parameter can be written in several ways, so a proxy rule based on it is
  easy to get around. If one Veriqa instance serves both an internal and a public application, give the internal
  one an instance of its own, with its own host name and issuer.
* **It does not suit consumer applications.** Your customers sign in from networks you do not
  control; the RFC itself notes this limitation.
* **The network is only as trusted as the way into it.** Guest Wi-Fi in the same range, a personal
  device on the VPN, or malware on an office computer is already inside. The RFC advises combining
  this control with others (§6.1.8, SHOULD), for example with the
  [Passkeys alongside Veriqa](https://veriqa.app/docs/scenarios/passkey-with-veriqa.md) scenario.
* **Remote work goes through the VPN.** An employee outside the office signs in only with the VPN on,
  and a VPN outage stops their sign-ins too.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.