Skip to content

Add localhost OAuth landing page before authorization redirect#84

Open
mjangda wants to merge 1 commit into
trunkfrom
add/oauth-landing-page
Open

Add localhost OAuth landing page before authorization redirect#84
mjangda wants to merge 1 commit into
trunkfrom
add/oauth-landing-page

Conversation

@mjangda

@mjangda mjangda commented Jun 12, 2026

Copy link
Copy Markdown
Member

Summary

Adds a localhost OAuth landing page that opens before the real OAuth authorization redirect. Instead of immediately bouncing the user's browser to the IdP, the proxy first opens a localhost page (GET /oauth/start on the callback server) showing which site is being authorized. The user reviews it and clicks through to the actual authorization URL.

This reduces the "surprise redirect" / phishing risk of an unattended jump to an external auth server.

The landing page is enabled by default. Set OAUTH_LANDING_PAGE=false to restore the previous direct-redirect behavior.

Screenshot 2026-06-12 at 02-44-15 — Screenshot 2026-06-12 at 02-44-44 — Screenshot 2026-06-12 at 02-43-58 — Screenshot 2026-06-12 at 02-44-29 —

Testing

  • New tests added.

To try it: npm run dev:oauth-html, then open the printed URL (default http://127.0.0.1:8765/).

Open the browser to a localhost landing page (GET /oauth/start on the
callback server) before the real OAuth authorization URL. The user
reviews which site they're authorizing, then clicks through — avoiding
an immediate redirect to the IdP and reducing surprise/phishing risk.
Enabled by default; set OAUTH_LANDING_PAGE=false to restore the previous
direct-redirect behavior.

- config: OAUTH_LANDING_PAGE (default true), exposed as oauthLandingPage
- oauth-callback-server: setLandingContext()/getLandingUrl() + GET
  /oauth/start route; extract callback HTML into oauth-html-templates
  and add landing/unavailable templates; clear landing state on stop()
- mcp-oauth-provider + persistent provider: open landing URL (or the
  authorize URL when disabled), with matching manual-fallback messaging
- dev: 'npm run dev:oauth-html' preview server for the OAuth HTML flows
- tests: formatSiteLabelForOAuthLanding unit tests
- docs: README + development.md

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a localhost OAuth “landing page” (GET /oauth/start on the callback server) that opens before redirecting the user to the external OAuth authorization endpoint, allowing the user to confirm which site is being authorized. It’s enabled by default and can be disabled via OAUTH_LANDING_PAGE=false.

Changes:

  • Add /oauth/start landing page support to the OAuth callback server and route browser opens through it by default.
  • Introduce shared OAuth HTML templates (landing + callback) and a dev-only HTML preview server (npm run dev:oauth-html).
  • Add config surface area and documentation updates for the landing page behavior and preview tooling.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/unit/oauth-landing.test.ts Adds unit tests for site-label formatting used on the landing page.
src/lib/persistent-oauth-client-provider.ts Routes browser open to landing page first (configurable) and improves manual fallback messaging.
src/lib/oauth-html-templates.ts New shared HTML/CSS templates for OAuth landing + callback flows.
src/lib/oauth-callback-server.ts Adds /oauth/start endpoint and landing context plumbing; moves callback HTML into templates module.
src/lib/mcp-oauth-provider.ts Routes browser open to landing page first (configurable) and improves manual fallback messaging.
src/lib/config.ts Adds OAUTH_LANDING_PAGE config/env flag (default enabled) and exposes it via getConfig().
src/dev/oauth-html-preview.ts New dev-only server to preview OAuth HTML flows without the full stack.
README.md Documents the new localhost landing page behavior and how to disable it.
package.json Adds dev:oauth-html script and includes the dev preview entry in tsup.
Docs/development.md Documents the new dev:oauth-html workflow and env overrides.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +65 to +72
this.app.get('/oauth/start', (req, res) => {
logger.oauth('OAuth landing page requested');
if (!this.landingAuthUrl) {
res.status(400).type('html').send(buildLandingUnavailableHtml());
return;
}
res.type('html').send(buildOAuthLandingHtml(this.landingAuthUrl, this.landingSiteLabel));
});
If this tab opened unexpectedly, close it.
</div>
<p class="a8c-oauth-actions"><a class="a8c-oauth-btn" href="${safeUrl}">Continue to authorization</a></p>
<p class="a8c-oauth-muted">This page is served only from your device (<span class="a8c-oauth-code">127.0.0.1</span>). It is not hosted by WordPress.com or your site.</p>
Comment on lines +185 to +193
export function buildOAuthLandingHtml(authUrl: string, siteLabel: string): string {
const safeUrl = escapeHtml(authUrl);
const safeSite = escapeHtml(siteLabel);
let authHost = '';
try {
authHost = escapeHtml(new URL(authUrl).hostname);
} catch {
/* ignore */
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants