n8n OAuth and Webhooks on Localhost
n8n combines incoming webhooks and OAuth credential flows in one self-hosted UI — you often need both a public webhook URL and an HTTPS redirect URI. OAuth theory lives in the OAuth redirect blog; steps are in OAuth callback on localhost.
Try it in 60 seconds
n8n webhooks default to localhost URLs external services cannot reach. Fix with one env var and a tunnel:
WEBHOOK_URL=https://k7m2x9p4q1.localtolink.com/ n8n start
npx localtolink --port 5678
Activate a workflow with a Webhook trigger. Copy the production URL from the node — it should show your tunnel domain. POST with curl; check n8n execution logs.
Why n8n needs a tunnel locally
n8n workflows often depend on external triggers — webhooks from third-party services, OAuth credentials for Google Sheets or Slack, and callback URLs that must be publicly reachable. When running n8n locally, these URLs default to localhost, which external services cannot call.
A development tunnel gives n8n a public HTTPS base URL for webhook nodes and OAuth credential flows.
Default n8n port
n8n typically runs on port 5678:
# Terminal 1
n8n start
# Terminal 2
npx localtolink --port 5678
If you use Docker or a custom port, adjust --port accordingly.
Configure webhook base URL
n8n generates webhook URLs based on its configured base URL. For local testing with a tunnel, set the WEBHOOK_URL environment variable:
WEBHOOK_URL=https://k7m2x9p4q1.localtolink.com/ n8n start
Replace k7m2x9p4q1 with the subdomain LocalToLink prints.
After setting this, Webhook nodes in your workflows show URLs like:
https://k7m2x9p4q1.localtolink.com/webhook/order-created
Update WEBHOOK_URL whenever the subdomain changes — each new tunnel session gets a random subdomain.
Testing webhook workflows
- Create a workflow with a Webhook trigger node
- Set HTTP method and path
- Activate the workflow
- Copy the production webhook URL from the node (uses
WEBHOOK_URL) - Send a test POST from curl or the external service:
curl -X POST https://k7m2x9p4q1.localtolink.com/webhook/test \
-H "Content-Type: application/json" \
-d '{"orderId": 123}'
- Check n8n's execution log for the received payload
Webhook POSTs are server-to-server. Some automated clients may reach your app differently than a first-time browser visit.
OAuth credentials in n8n
For nodes requiring OAuth (Google Sheets, Slack, GitHub, etc.):
1. Register redirect URI in the provider's developer console:
https://k7m2x9p4q1.localtolink.com/rest/oauth2-credential/callback
This is n8n's standard OAuth callback path.
2. Create credentials in n8n using the same OAuth app client ID and secret.
3. Complete the OAuth flow in a browser by opening n8n through the tunnel URL:
https://k7m2x9p4q1.localtolink.com
On first visit in a browser, continue through any LocalToLink safety prompt.
4. Click "Connect" on the credential — the OAuth popup redirects through the tunnel callback.
See OAuth Callback on Localhost for general OAuth guidance and provider-specific tips.
n8n UI through the tunnel
Access the n8n editor at the tunnel URL for testing from another device or sharing with a colleague. The n8n UI uses WebSockets for real-time updates — LocalToLink supports WebSocket passthrough for browser access.
Docker setup
If n8n runs in Docker:
docker run -p 5678:5678 \
-e WEBHOOK_URL=https://k7m2x9p4q1.localtolink.com/ \
n8nio/n8n
npx localtolink --port 5678
Ensure the tunnel forwards to the host port mapped to the container.
Production webhook URL vs tunnel URL
Self-hosted n8n stores WEBHOOK_URL at startup. If you change tunnels mid-session, restart n8n or update the env var so trigger URLs in the UI match the active subdomain. OAuth redirect URIs must use the same host — a mismatch of even one trailing slash breaks the flow. The OAuth callback guide walks through exact URI registration.
Important notes
- Session limit: 2 hours, 1 GB bandwidth on free tier
- Random subdomain — update
WEBHOOK_URLand OAuth redirect URIs on each new session - Custom subdomains not available on the free tier yet
- No request inspector — check n8n execution logs for webhook payloads
- 1 tunnel per IP on free tier
Troubleshooting
| Problem | Fix |
|---|---|
| Webhook URL shows localhost | Set WEBHOOK_URL before starting n8n |
| OAuth redirect fails | Register tunnel callback URL in provider console |
| Workflow not triggering | Confirm workflow is activated (not just saved) |
| Session ended | Restart tunnel and update URLs |
| OAuth popup blocked | Allow popups; complete flow through tunnel URL |
FAQ
Can I use n8n's built-in tunnel?
n8n Cloud handles this automatically. For self-hosted local development, LocalToLink or similar is needed.
Do test webhooks need HTTPS?
External services require HTTPS. curl tests work through the tunnel URL directly.
What about n8n queue mode?
Webhook triggers still need the public URL pointing to the main n8n instance that receives webhooks.
See Test Webhooks Locally for the general webhook hub.
Try it now
Start a tunnel from your project directory — no account required.
$ npx --yes localtolink@latest