Skip to content

Feature Request: Extend WordPress.com authentication session duration #3090

Description

@georgestephanis

Note on research process: The investigation underlying this issue was conducted with AI assistance (Claude via Claude Code). The AI was used to trace the authentication code paths, read the WordPress.com OAuth2 documentation, and reason about the available implementation options. Findings were reviewed and verified by a human before filing.

What

Extend the duration of WordPress.com login sessions in Studio so that users are not required to re-authenticate every two weeks. Ideally, sessions should persist until the user explicitly logs out.

Why

Currently, Studio uses the OAuth 2.0 Implicit Flow (response_type=token) to authenticate with WordPress.com. This flow returns an access token directly in the redirect URL fragment with a fixed expires_in of approximately two weeks. Studio stores this expiration timestamp locally and treats the token as invalid once it passes — requiring the user to log in again.

This is frustrating in practice: a user who installs Studio and logs in will silently lose their authenticated session roughly every fortnight, with no background renewal possible.

Root cause in the codebase

Two separate code paths both enforce the two-week limit:

  • Desktop app (apps/studio/src/lib/deeplink/handlers/auth.ts): stores expirationTime directly from the server's expires_in response field.
  • CLI (apps/cli/commands/auth/login.ts): ignores the server's expires_in and hardcodes DEFAULT_TOKEN_LIFETIME_MS = DAY_MS * 14 from tools/common/constants.ts.

Both paths are then subject to a local expiry check in tools/common/lib/shared-config.ts:

if ( Date.now() >= token.expirationTime ) {
    return null;  // forces re-authentication
}

Why a trivial local fix won't help

The two-week limit is not just a local artifact — it reflects the server-side lifetime of Implicit Flow tokens issued by WordPress.com's OAuth server. Relaxing or removing the local expiry check would still result in invalid_token API errors once the server-side token expires, which Studio already handles by forcing a logout.

Why the obvious alternative (PKCE) isn't currently available

For native/desktop apps, the standard solution to this problem is to switch from the Implicit Flow to the Authorization Code Flow with PKCE (RFC 7636). PKCE allows a public client (one that cannot safely store a client_secret) to use the Auth Code Flow securely. Auth Code Flow tokens are typically longer-lived or non-expiring, and the flow also supports refresh tokens for silent renewal.

However, PKCE is not currently documented or supported by WordPress.com's OAuth2 server (public-api.wordpress.com/oauth2/). The Authorization Code Flow is supported, but it requires a client_secret for the token exchange — which cannot be safely embedded in a distributed desktop application binary.

How

Three implementation paths are available, roughly ordered by preference:

Option A — Request PKCE support from the WordPress.com platform team (preferred)

PKCE is a well-understood, additive extension to the existing Auth Code Flow (RFC 7636). The server-side implementation is modest:

  1. Accept code_challenge and code_challenge_method parameters on the authorization endpoint; store them alongside the short-lived auth code.
  2. On the token endpoint, validate the incoming code_verifier by computing BASE64URL(SHA256(code_verifier)) and comparing it to the stored challenge.
  3. Optionally enforce PKCE for public clients (RFC 9700 best practice).

This is roughly 1–3 days of engineering work for someone familiar with their OAuth codebase, plus review. It is not an architectural change — it slots into the existing Authorization Code Flow infrastructure.

Impact for Studio: Studio's tools/common/lib/oauth.ts would switch from response_type=token to response_type=code, generate a PKCE code verifier/challenge per login, and exchange the returned code for a token via POST /oauth2/token. No client_secret needed. If refresh tokens are also issued, tools/common/lib/auth-token-schema.ts and tools/common/lib/shared-config.ts would be updated to store and silently refresh them.

This benefits not just Studio but all public OAuth clients building on the WordPress.com platform.


Option B — Proxy service for Authorization Code Flow (secure, requires new infrastructure)

A small Studio-owned backend endpoint holds the client_secret and handles the token exchange server-to-server. The flow:

  1. Studio opens the WordPress.com authorization URL with response_type=code.
  2. WordPress.com redirects back with a code via the wp-studio://auth deeplink.
  3. Studio sends the code to the proxy endpoint, which exchanges it for an access token using the client_secret.
  4. The proxy returns the token to Studio.

This keeps the secret off the client binary entirely and should yield long-lived (or non-expiring) Authorization Code tokens. The documented Auth Code token response notably omits expires_in, suggesting tokens from this flow may not expire.

Trade-off: Requires operating and maintaining a backend service. Adds a network dependency to the login flow. Feels somewhat silly when A8C also runs the endpoint we're authenticating to.


Option C — Embed client_secret in the desktop app (pragmatic, lower security bar)

Many open-source desktop apps (VS Code, GitHub Desktop) embed OAuth secrets directly in their binaries, accepting that the secret is technically extractable. Studio already embeds CLIENT_ID = '95109' in tools/common/constants.ts.

Adding CLIENT_SECRET and switching to response_type=code with a direct token exchange from the desktop process would be a self-contained change with no new infrastructure. If Auth Code tokens are long-lived or non-expiring, this immediately solves the user-facing problem.

Trade-off: The secret is extractable from the binary. For an open-source app where the source is already public, the marginal risk is low — but it is not best practice and would need a deliberate security sign-off.


Summary

Option Infrastructure Security Complexity Solves re-auth?
A — PKCE (platform change) None Best Low (server-side) Yes, with refresh tokens
B — Proxy backend New service required Best Medium Yes
C — Embedded secret None Acceptable for OSS desktop Low Yes (if Auth Code tokens are long-lived)

The recommended first step is to open a conversation with the WordPress.com platform team about Option A, since it is the most correct solution and benefits the broader developer ecosystem. Options B and C are available as fallbacks if PKCE support is not forthcoming.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions