Turning one click into a temporary firewall rule is convenient, and it also builds an authorization system that decides who may reach a service. What it issues is an address rather than a person, and that difference matters the moment two people share a NAT. Scope the grant, confirm it deliberately, and make expiry mean something before the link is built. The decision in front of you is where to put the boundary, not whether one should exist.

Decide which question the grant answers

Start from the requirement. If a named person must reach the service and the application already authenticates that person, an authenticated gateway keeps identity at the enforcement point and needs no address admission at all. If the target is a build agent, an administrative jump port or an appliance that cannot take part in user login, a scoped address grant may be the only practical control available.

Choosing address admission for a user-facing application moves the real authorization problem somewhere else, and the portal then inherits the blame for a gap it never closed.

Bound the request on the server

The browser must not choose the destination, the port or the prefix. The portal resolves the service from its own records and checks entitlement with a server-side test, which is the same principle OWASP's authorization guidance applies to every request. Address derivation belongs at the protected boundary as well: when a reverse proxy reports the client address, accept only the configured proxy chain and its documented header handling. A forwarding header supplied by a visitor is an assertion about provenance, not evidence of it.

Then check that the portal and the service observe the same source. Split tunnelling, a proxy hop and IPv4 versus IPv6 can hand two destinations two different addresses, so a grant activated from one path may not cover the request that follows.

Show the grant before installing it

Opening a link should render the proposed service, the observed source and the duration, and change nothing yet. That single step converts the emailed link from an action into a proposal, and it stops a preview bot or a mail scanner from granting access simply by fetching it.

The confirmation should be a state-changing request with the usual cross-site and origin defences. The token should be single-use and consumed atomically at the moment the rule is installed, and the record should capture the owner, service, address, grant identifier and expiry without ever logging the raw token.

Token delivery deserves the same care as the rule itself. An expired or already consumed link that still produces a rule is a second door fitted with the same key.

The address is shared even while the grant lives

An office NAT, a carrier NAT and a shared VPN exit each put several people behind one address. Admitting that address admits everyone behind it as far as the service's next boundary is concerned, while proving nothing about who holds the account the service expects.

Removing the rule is not a universal disconnect either. Established connections, cached application tokens and long-lived sessions can outlive the rule by minutes or by far longer, so the lifetime you pick should reflect what the service does after admission rather than only how long the rule exists.

Test four cases, and both address families

A grant is only as good as the four cases it survives: a fresh allowed request, an unapproved requester, a replay of the same link, and the same request after expiry.

Then test each family separately, because the source address the service observes can differ between them.

dig +short A service.example.com
dig +short AAAA service.example.com
curl -4 -sS -o /dev/null -w "%{http_code}\n" https://service.example.com
curl -6 -sS -o /dev/null -w "%{http_code}\n" https://service.example.com

The useful outcome is a temporary, auditable admission decision sitting under normal user authorization, rather than a permanent opening carrying the name of whoever clicked first.

Related articles