Skip to content

feat(backend,nextjs): add experimental poppy browser sessions - #10702

Draft
thiskevinwang wants to merge 5 commits into
mainfrom
kevin/poppy-v04-browser-session
Draft

thiskevinwang wants to merge 5 commits into
mainfrom
kevin/poppy-v04-browser-session

Conversation

@thiskevinwang

@thiskevinwang thiskevinwang commented Nov 6, 2026 •

Copy link
Copy Markdown
Member

Description

Important

Experimental Poppy v0.4 support for signed-in browsing with full account access. Clerk hosts the browser session endpoint; the application uses normal Clerk authentication.

Clerk selects the full-account-access browsing profile: Poppy-defined web.unscoped: true makes poppy:browser-sign-in authorize website access with the account's permissions. This fits applications that use Clerk Sessions and do not enforce OAuth scopes on each page.

The Poppy-defined browser join uses GET {J}, POST {J}/authorize, and POST {J}, where {J} is the advertised web.browser_session_endpoint. A successful signed-in form POST creates and activates a Clerk Session directly, then returns 303 to the application with Clerk's existing navigation handshake. The SDK applies the session cookies and reads the normal Clerk Session JWT. No Clerk ticket redemption or customer callback page is required.

stateDiagram-v2
    direction LR
    state "Discovery" as Discovery
    state "OAuth consent" as OAuth
    state "Poppy browser join" as BrowserJoin
    state "Clerk Session created" as ClerkSession
    state "Clerk handshake" as Handshake
    state "Authenticated application" as Application

    Discovery --> OAuth
    OAuth --> BrowserJoin
    BrowserJoin --> ClerkSession: POST form
    ClerkSession --> Handshake: 303 to application
    Handshake --> Application: Session cookies
Loading
Proposed SDK usage guide — Next.js

[!IMPORTANT]
Experimental support for signed-in browsing with full account access. Clerk hosts the Poppy-defined browser session endpoint and uses Clerk's existing handshake to establish application cookies.

Start with the normal Clerk Next.js setup. Enable Poppy for the instance and serve discovery on its configured primary domain.

1. Enable discovery in proxy.ts, alongside normal Clerk route protection.

import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';

const isProtectedRoute = createRouteMatcher(['/account(.*)']);

export default clerkMiddleware(
  async (auth, request) => {
    if (isProtectedRoute(request)) await auth.protect();
  },
  {
    // Clerk-defined preview option: serves discovery on the application domain.
    // Controls discovery only; enable Poppy for the instance server-side.
    __experimental_poppy: true,
  },
);

export const config = {
  matcher: [
    '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
    '/(api|trpc)(.*)',
  ],
};

The SDK serves /.well-known/poppy.json (Poppy-defined) and /.well-known/oauth-protected-resource (OAuth-defined). Clerk supplies the hosted endpoint URL.

2. Read normal Clerk authentication.

import { auth } from '@clerk/nextjs/server';

const { userId, sessionId, agent } = await auth();

// Common Clerk-defined agent fields.
const agentId = agent?.sub;
const taskId = agent?.task_id;

userId and sessionId identify the signed-in Clerk user and session. The Clerk-defined agent object uses the same shape for Poppy and other agent sessions: type: 'agent', sub for the agent identifier, and task_id when a Clerk agent task is associated with the session. Signed-out visitors have no authenticated agent identity.

Clerk maps Poppy identification to this common agent shape. Agent-authenticated requests use Clerk's normal Session JWT verification and session lifecycle.

Checklist

  • Backend SDK Node tests and focused edge-runtime tests pass.
  • Backend SDK build and declarations pass.
  • (If applicable) JSDoc comments have been added or updated for package exports.
  • (If applicable) Documentation has been updated.

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

@vercel

vercel Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
clerk-js-sandbox Ready Ready Preview Nov 11, 2026 9:24pm UTC
swingset Ready Ready Preview Nov 11, 2026 9:24pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
Pre-merge checks: Inconclusive 2

Failed Failed checks: 2 inconclusive

Check name Status Explanation Resolution
Title check Pending This assessment has not completed. The check will be retried on the next pre-merge check run.
Description check Pending This assessment has not completed. The check will be retried on the next pre-merge check run.
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@changeset-bot

changeset-bot Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8dbea17

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@clerk/backend Minor
@clerk/nextjs Minor
@clerk/astro Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/hono Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch
@clerk/swingset Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@10702

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@10702

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@10702

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@10702

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@10702

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@10702

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@10702

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@10702

@clerk/expo-biometrics

npm i https://pkg.pr.new/@clerk/expo-biometrics@10702

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@10702

@clerk/expo-native-components

npm i https://pkg.pr.new/@clerk/expo-native-components@10702

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@10702

@clerk/express

npm i https://pkg.pr.new/@clerk/express@10702

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@10702

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@10702

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@10702

@clerk/mosaic

npm i https://pkg.pr.new/@clerk/mosaic@10702

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@10702

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@10702

@clerk/react

npm i https://pkg.pr.new/@clerk/react@10702

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@10702

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@10702

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@10702

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@10702

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@10702

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@10702

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@10702

commit: 8dbea17

@thiskevinwang
thiskevinwang force-pushed the kevin/poppy-v04-browser-session branch from 6e672b1 to 0b8dc07 Compare November 6, 2026 21:58
@thiskevinwang
thiskevinwang force-pushed the kevin/poppy-v04-browser-session branch from 0b8dc07 to ac99b0b Compare November 7, 2026 00:32
@thiskevinwang
thiskevinwang force-pushed the kevin/poppy-v04-browser-session branch from ac99b0b to 12887af Compare November 7, 2026 01:08
@thiskevinwang
thiskevinwang force-pushed the kevin/poppy-v04-browser-session branch from 12887af to 67b7431 Compare November 7, 2026 01:23
@thiskevinwang
thiskevinwang force-pushed the kevin/poppy-v04-browser-session branch from 67b7431 to ebb9b68 Compare November 7, 2026 05:13
@thiskevinwang
thiskevinwang force-pushed the kevin/poppy-v04-browser-session branch from ebb9b68 to d214318 Compare November 9, 2026 01:41
@github-actions github-actions Bot added the nextjs label Nov 9, 2026
@thiskevinwang
thiskevinwang force-pushed the kevin/poppy-v04-browser-session branch from d214318 to 170e4c6 Compare November 9, 2026 01:55
@thiskevinwang
thiskevinwang force-pushed the kevin/poppy-v04-browser-session branch from 170e4c6 to 7747bb8 Compare November 9, 2026 03:20
import { PoppyCallback } from '../app-router/client/PoppyCallback';
import { decryptClerkRequestData } from './utils';

export async function PoppyCallbackPage() {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

💭 If this is meant to be mounted at an already clerk-derived path, eg. {J}/callback 1, then it feels more appropriate to handle entirely in middleware/proxy.

  • [benefit] 1 less component to mount; 1 less path to fat-finger-wrong.

Footnotes

  1. {J} = {browser_session_endpoint} ↩

@thiskevinwang thiskevinwang Nov 10, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Update: FAPI interaction, primarily ...

signIn.create({ strategy: 'ticket', ticket })

...needs to happen client side.

@thiskevinwang
thiskevinwang force-pushed the kevin/poppy-v04-browser-session branch from 60336ae to 0e7b6c4 Compare November 10, 2026 20:43
@thiskevinwang thiskevinwang changed the title feat(backend): add Poppy browser session helpers feat(nextjs): discover hosted Poppy browser sessions Nov 10, 2026
@thiskevinwang
thiskevinwang force-pushed the kevin/poppy-v04-browser-session branch from 0e7b6c4 to 38c6629 Compare November 10, 2026 21:09
@thiskevinwang
thiskevinwang force-pushed the kevin/poppy-v04-browser-session branch from 38c6629 to 3c7ff3c Compare November 11, 2026 00:44
@thiskevinwang
thiskevinwang force-pushed the kevin/poppy-v04-browser-session branch from 3c7ff3c to 5342ea4 Compare November 11, 2026 00:48

Copy link
Copy Markdown
Member Author

!snapshot

@github-actions

Copy link
Copy Markdown
Contributor

Hey @thiskevinwang - the snapshot version command generated the following package versions:

Package Version
@clerk/astro 4.1.23-snapshot.v20261112145506
@clerk/backend 3.28.0-snapshot.v20261112145506
@clerk/chrome-extension 3.1.106-snapshot.v20261112145506
@clerk/clerk-js 6.42.4-snapshot.v20261112145506
@clerk/electron 0.1.11-snapshot.v20261112145506
@clerk/electron-passkeys 0.0.4-snapshot.v20261112145506
@clerk/eslint-plugin 0.2.1-snapshot.v20261112145506
@clerk/expo 4.15.2-snapshot.v20261112145506
@clerk/expo-biometrics 1.1.1-snapshot.v20261112145506
@clerk/expo-google-signin 1.1.1-snapshot.v20261112145506
@clerk/expo-native-components 0.4.5-snapshot.v20261112145506
@clerk/expo-passkeys 2.1.8-snapshot.v20261112145506
@clerk/express 2.1.89-snapshot.v20261112145506
@clerk/fastify 3.1.99-snapshot.v20261112145506
@clerk/hono 0.1.99-snapshot.v20261112145506
@clerk/localizations 4.24.7-snapshot.v20261112145506
@clerk/mosaic 0.3.0-snapshot.v20261112145506
@clerk/msw 0.0.87-snapshot.v20261112145506
@clerk/nextjs 7.10.0-snapshot.v20261112145506
@clerk/nuxt 3.1.23-snapshot.v20261112145506
@clerk/react 6.18.7-snapshot.v20261112145506
@clerk/react-router 3.7.1-snapshot.v20261112145506
@clerk/shared 4.44.2-snapshot.v20261112145506
@clerk/swingset 0.0.70-snapshot.v20261112145506
@clerk/tanstack-react-start 1.7.12-snapshot.v20261112145506
@clerk/testing 2.2.56-snapshot.v20261112145506
@clerk/ui 1.42.5-snapshot.v20261112145506
@clerk/upgrade 2.0.12-snapshot.v20261112145506
@clerk/vue 2.5.20-snapshot.v20261112145506

Tip: Use the snippet copy button below to quickly install the required packages.
@clerk/astro

npm i @clerk/astro@4.1.23-snapshot.v20261112145506 --save-exact

@clerk/backend

npm i @clerk/backend@3.28.0-snapshot.v20261112145506 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.1.106-snapshot.v20261112145506 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.42.4-snapshot.v20261112145506 --save-exact

@clerk/electron

npm i @clerk/electron@0.1.11-snapshot.v20261112145506 --save-exact

@clerk/electron-passkeys

npm i @clerk/electron-passkeys@0.0.4-snapshot.v20261112145506 --save-exact

@clerk/eslint-plugin

npm i @clerk/eslint-plugin@0.2.1-snapshot.v20261112145506 --save-exact

@clerk/expo

npm i @clerk/expo@4.15.2-snapshot.v20261112145506 --save-exact

@clerk/expo-biometrics

npm i @clerk/expo-biometrics@1.1.1-snapshot.v20261112145506 --save-exact

@clerk/expo-google-signin

npm i @clerk/expo-google-signin@1.1.1-snapshot.v20261112145506 --save-exact

@clerk/expo-native-components

npm i @clerk/expo-native-components@0.4.5-snapshot.v20261112145506 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@2.1.8-snapshot.v20261112145506 --save-exact

@clerk/express

npm i @clerk/express@2.1.89-snapshot.v20261112145506 --save-exact

@clerk/fastify

npm i @clerk/fastify@3.1.99-snapshot.v20261112145506 --save-exact

@clerk/hono

npm i @clerk/hono@0.1.99-snapshot.v20261112145506 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.24.7-snapshot.v20261112145506 --save-exact

@clerk/mosaic

npm i @clerk/mosaic@0.3.0-snapshot.v20261112145506 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.87-snapshot.v20261112145506 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.10.0-snapshot.v20261112145506 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@3.1.23-snapshot.v20261112145506 --save-exact

@clerk/react

npm i @clerk/react@6.18.7-snapshot.v20261112145506 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.7.1-snapshot.v20261112145506 --save-exact

@clerk/shared

npm i @clerk/shared@4.44.2-snapshot.v20261112145506 --save-exact

@clerk/swingset

npm i @clerk/swingset@0.0.70-snapshot.v20261112145506 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.7.12-snapshot.v20261112145506 --save-exact

@clerk/testing

npm i @clerk/testing@2.2.56-snapshot.v20261112145506 --save-exact

@clerk/ui

npm i @clerk/ui@1.42.5-snapshot.v20261112145506 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.12-snapshot.v20261112145506 --save-exact

@clerk/vue

npm i @clerk/vue@2.5.20-snapshot.v20261112145506 --save-exact

This branch was successfully deployed

2 active deployments
Preview – swingset — 8dbea171 Deployed Nov 11, 2026 by vercel[bot]
Preview – clerk-js-sandbox — 8dbea171 Deployed Nov 11, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant