Skip to guide

Dev Tunnels 401 Unauthorized: webhook and OAuth callback checks

Webhook or OAuth callback getting 401 from Dev Tunnels?

Dev Tunnels are private by default, so a webhook sender that can’t sign in can get a 401 from the tunnel before the request reaches your app. Send a tunnel access token in the X-Tunnel-Authorization header, or allow anonymous access to that port and keep validating webhook signatures in your app.

Why does a callback return 401 before reaching my app?

A private tunnel and your application can each authenticate requests. Compare the failing response with local application logs before deciding which layer rejected it. A successful browser visit does not prove that a separate webhook sender can access the same endpoint.

A May 2024 Dev Tunnels report describes an OAuth callback POST returning 401 before reaching the app, with WWW-Authenticate: tunnel in the response. The reporter resolved that setup with anonymous tunnel access. The remaining cookie question was not conclusively diagnosed; this is not evidence that all current callbacks fail.

What should I check before changing access?

Check the exact public callback address, path and port against the provider configuration. Use devtunnel access list TUNNELID to review the intended tunnel access entries. Also verify the local app accepts the expected method and authenticates the request correctly.

Separate CLI host login, visitor access and application authorization. A webhook sender normally cannot complete an interactive browser sign-in. Preserve application logs without recording OAuth codes, tokens, cookies or webhook payloads in shared diagnostics.

Can a non-interactive sender use a private tunnel?

When the sender supports a custom request header, Microsoft documents devtunnel token TUNNELID --scopes connect and the header X-Tunnel-Authorization: tunnel <TOKEN>. Keep the token private and account for expiration. This authorizes tunnel access; the app may still require its own credentials.

The separate tunnel header avoids replacing application Authorization. Do not substitute a host or management token, and do not assume a webhook provider or browser OAuth form can attach a custom header.

What if the sender cannot authenticate to the tunnel?

Only consider anonymous tunnel access when the intended local service can safely be reached from the internet. Review the affected port and existing access entries rather than exposing unrelated services. Microsoft documents port-specific anonymous access; follow its current CLI reference for your configuration.

Retain application authorization and provider-specific webhook signature validation. For GitHub deliveries, validate the signature with the configured webhook secret before processing the request. Anonymous tunnel access does not make an unvalidated callback trustworthy.

Will skipping the warning page fix a private-tunnel 401?

No. Microsoft documents anti-phishing interstitial handling separately from access authorization, and non-GET requests already skip that page. A skip-warning header does not grant access to a private tunnel.

After correcting the relevant layer, send one harmless test delivery and confirm it reaches the app. If the app itself rejects it, inspect its authentication or callback configuration instead of changing tunnel access again.

Can I test the same local HTTP workflow with Groundhog?

Groundhog provides named public HTTPS addresses through its CLI or Aspire integration. Keep app authentication and webhook validation, update the registered callback address, and verify a test request reaches the intended local app.

Groundhog is free and best effort with workspace and shared-service limits. Changing providers does not repair an incorrect callback URL or application authentication failure.

Sources

Sources reviewed . Provider behavior and limits can change.

Try Groundhog for your local HTTP app

Use a named public HTTPS address with the CLI or Aspire. There’s no monthly data cap; per-minute and concurrent-request limits apply.