Skip to main content

Device Identity Tag (BYOD access gating)

The Device Identity Tag lets you prove that a web request comes from a device that has the Surface extension installed, so firewalls, secure web gateways, and SaaS apps can gate sensitive resources to Surface-protected devices — without MDM enrollment or distributing device certificates to third parties.

It is off by default and configured per tenant under Settings → Device Identity Tag.


What it does

When enabled, the Surface extension adds a short, tenant-scoped tag to every outbound website request in two places:

  • The User-Agent header gets a suffix: SurfaceSec/1.0 (t:<TAG>)
  • A dedicated X-Surface-Device request header: t=<TAG>
User-Agent: Mozilla/5.0 (...) Chrome/140.0 Safari/537.36 SurfaceSec/1.0 (t:K7M2QX)
X-Surface-Device: t=K7M2QX

Your perimeter (firewall / SWG / proxy / WAF) inspects these values and allows or blocks the request. A device without the extension simply doesn't send them, so it fails the check.

The Surface API endpoint itself is excluded from tagging, so backend communication is unaffected.

The tenant tag (t)

  • A 6-character, unambiguous code (e.g. K7M2QX) shown on the settings page.
  • Immutable once generated. It does not reveal your organization name.
  • You can Regenerate it from the settings page (requires re-authentication). Regenerating invalidates every firewall/SaaS filter keyed on the old tag — plan a cutover before you do it.

This is an access-convenience signal, not strong authentication. A determined user could spoof a User-Agent or header. Use it to gate access for convenience and to reduce exposure, ideally alongside your existing identity and network controls — not as your only line of defense for highly sensitive systems.


Optional: user correlation token (u)

A second toggle adds a daily-rotating, pseudonymous token that lets you tie a session in a third-party log back to a specific user — without exposing the user's identity to that third party.

User-Agent: ... SurfaceSec/1.0 (t:K7M2QX u:ab12cd34ef56)
X-Surface-Device: t=K7M2QX; u=ab12cd34ef56
  • The u value is 12 hex characters that change every day (UTC midnight).
  • The user's real identity never appears on the wire. Only your Surface server can resolve a token back to a user, using the Resolve a user token tool on the same settings page.
  • Requires User-Agent tagging to be enabled first.
  • It is privacy-sensitive — enable it deliberately. Every resolution (and every tag regeneration) is recorded in the audit log.

Resolving a token

On Settings → Device Identity Tag, paste the 12-character u: value from a log into Resolve a user token. Leave the day blank to check today and yesterday (UTC). Surface returns the matching user, or "no match." This is intended for occasional incident-response / SIEM lookups.


Setting it up

1. Enable it in Surface

  1. Go to Settings → Device Identity Tag.
  2. Turn on Enable User-Agent tagging. Your tenant tag is generated immediately — copy it.
  3. (Optional) Turn on User correlation token if you need per-user session correlation in your own logs.

Extensions pick up the change on their next policy sync (within ~1 hour, or immediately on restart).

2. Gate access at your perimeter

Match on the X-Surface-Device header where you can (most reliable — some proxies normalize or strip the User-Agent), or fall back to the User-Agent.

Match targetValue to look for
X-Surface-Device headercontains t=K7M2QX
User-Agent substringcontains SurfaceSec/1.0 (t:K7M2QX
User-Agent regexSurfaceSec/\d+\.\d+ \(t:K7M2QX(?: u:[0-9a-f]{12})?\)

The settings page renders these examples pre-filled with your real tag.

If you also use Surface's curl-UA countermeasure, it can override the User-Agent on suspicious domains. The X-Surface-Device header is unaffected, so prefer header-based matching when both features are on.


Platform integration guides

Microsoft Entra ID — read this first

Entra Conditional Access cannot natively gate on a custom header or a User-Agent substring. Its conditions are user/group, app, location (IP), device platform (parsed from the UA but unverified), and device state (compliant / hybrid-joined) — and device state requires the device to be Entra-registered or Intune-managed, which defeats the BYOD-without-MDM goal.

To use the tag with Entra-protected apps (e.g. Microsoft 365) you need Conditional Access App Control + Microsoft Defender for Cloud Apps (MDCA), which session-proxies the traffic and can filter on the User-Agent string (MDCA licensing required):

  1. In Entra → Conditional Access, create a policy for the target users/apps and under Session, select Use Conditional Access App Control (custom policy → route to Defender for Cloud Apps).
  2. In Microsoft Defender for Cloud Apps → Policies, create an Access policy (or Session policy) for the app.
  3. Add a filter on User agent stringdoes not containSurfaceSec/ and set the action to Block. (Match on the User-Agent tag here, not the X-Surface-Device header — MDCA inspects the user-agent string.)

If you don't have MDCA, gate these apps at a secure web gateway / proxy instead (below), or restrict them to managed-network egress IPs.

Secure web gateways / SASE

  • Zscaler — create an HTTP Header Profile (User-Agent / custom header) and reference it from a URL Filtering policy via the HTTP Header Profile criterion. Allow when X-Surface-Device is present; block otherwise.
  • Netskope — create an HTTP Header profile and an HTTP Header Policy / real-time protection policy that matches the header or User-Agent, then allow or block.
  • Cloudflare — a WAF custom rule or Gateway HTTP policy matching http.request.headers["x-surface-device"] (or the User-Agent). Block when the header is missing or doesn't contain your tag. See Cloudflare's "Require specific HTTP headers" use case.

Reverse proxy / WAF in front of a self-hosted app

Allow only requests carrying the header for your tag. Example (NGINX):

# Block anything without the Surface device tag for this tenant.
if ($http_x_surface_device !~* "t=K7M2QX") { return 403; }

The same pattern applies to Envoy, HAProxy, Azure Application Gateway WAF custom rules, AWS WAF, etc. — match the request header, allow or deny.


Privacy and data handling

  • Passwords and credentials are never involved; this feature only adds a tag to request headers.
  • With user correlation off, nothing user-identifying is sent — third parties see only the tenant tag, which is shared by all your devices.
  • With user correlation on, third parties see only the daily pseudonymous token; resolving it to a user is possible only inside Surface and is audit logged.
  • The daily token rotates at UTC midnight and cannot be linked across days by an outside observer.

Troubleshooting

SymptomCheck
Tag not appearing on requestsConfirm tagging is enabled and the device has synced policy (restart the browser to force it). The Surface API host is intentionally excluded.
Tag shows on UA but not X-Surface-Device (or vice-versa)Some proxies strip/normalize headers; verify your perimeter isn't removing them before your rule runs.
User-Agent missing the tag on certain sitesThe curl-UA countermeasure may have overridden the UA on a suspicious domain — match the X-Surface-Device header instead.
Resolve tool returns "no match"Confirm the day (try blank for today+yesterday UTC) and that user correlation was enabled when the token was emitted.
Need to rotate the tagUse Regenerate on the settings page, then update every perimeter rule to the new tag (old filters stop matching immediately).