-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
feat: add Descope #7756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mariamantsurova
wants to merge
3
commits into
TanStack:main
Choose a base branch
from
mariamantsurova:docs/add-start-descope-example
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
feat: add Descope #7756
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "image": "mcr.microsoft.com/devcontainers/typescript-node:24" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # Your Descope Project ID (found at https://app.descope.com/settings/project). | ||
| # Exposed to the browser for the client-side auth flow, so it must be VITE_ prefixed. | ||
| VITE_DESCOPE_PROJECT_ID=<YOUR_PROJECT_ID> | ||
|
|
||
| # The same Project ID, read by the server to validate sessions. | ||
| DESCOPE_PROJECT_ID=<YOUR_PROJECT_ID> | ||
|
|
||
| # Optional. Only needed for a custom domain (CNAME), a self-hosted Descope | ||
| # instance, or a non-default region (e.g. the EU cluster: https://api.euc1.descope.com). | ||
| # VITE_DESCOPE_BASE_URL= | ||
| # DESCOPE_BASE_URL= |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| node_modules | ||
| # Keep environment variables out of version control | ||
| !.env.example | ||
| package-lock.json | ||
| yarn.lock | ||
|
|
||
| .DS_Store | ||
| .cache | ||
| .env | ||
| .vercel | ||
| .output | ||
| /build/ | ||
| /api/ | ||
| /server/build | ||
| /public/build | ||
| # Sentry Config File | ||
| .env.sentry-build-plugin | ||
| /test-results/ | ||
| /playwright-report/ | ||
| /blob-report/ | ||
| /playwright/.cache/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| **/build | ||
| **/public | ||
| pnpm-lock.yaml | ||
| routeTree.gen.ts |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "files.watcherExclude": { | ||
| "**/routeTree.gen.ts": true | ||
| }, | ||
| "search.exclude": { | ||
| "**/routeTree.gen.ts": true | ||
| }, | ||
| "files.readonlyInclude": { | ||
| "**/routeTree.gen.ts": true | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| # TanStack Start + Descope | ||
|
|
||
| A [TanStack Start](https://tanstack.com/start) example demonstrating how to authenticate users with [Descope](https://www.descope.com): the [`@descope/react-sdk`](https://www.npmjs.com/package/@descope/react-sdk) renders the sign-in flow on the client, and the [`@descope/node-sdk`](https://www.npmjs.com/package/@descope/node-sdk) validates sessions on the server during SSR. | ||
|
|
||
| - [TanStack Router Docs](https://tanstack.com/router) | ||
| - [Descope Documentation](https://docs.descope.com) | ||
|
|
||
| ## Start a new project based on this example | ||
|
|
||
| To start a new project based on this example, run: | ||
|
|
||
| ```sh | ||
| npx gitpick TanStack/router/tree/main/examples/react/start-descope start-descope | ||
| ``` | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| You will need a [Descope account](https://www.descope.com/sign-up). Every project ships with a default `sign-up-or-in` flow, which is what this example renders — no extra flow setup is required. | ||
|
|
||
| ## Running the example | ||
|
|
||
| 1. Grab your **Project ID** from the [Descope console](https://app.descope.com/settings/project). | ||
| 2. Copy `.env.example` to `.env` and fill in your Project ID: | ||
|
|
||
| ```bash | ||
| cp .env.example .env | ||
| ``` | ||
|
|
||
| ```bash | ||
| # Exposed to the browser for the client-side auth flow (must be VITE_ prefixed) | ||
| VITE_DESCOPE_PROJECT_ID=<YOUR_PROJECT_ID> | ||
| # The same Project ID, read by the server to validate sessions | ||
| DESCOPE_PROJECT_ID=<YOUR_PROJECT_ID> | ||
| ``` | ||
|
|
||
| > [!NOTE] | ||
| > If you are using a custom domain (CNAME), or a private environment (for example `star`), also set `VITE_DESCOPE_BASE_URL` and `DESCOPE_BASE_URL`. | ||
|
|
||
| 3. Run the following command and navigate to [http://localhost:3000](http://localhost:3000). | ||
|
|
||
| ```bash | ||
| pnpm dev | ||
| ``` | ||
|
|
||
| ## Build | ||
|
|
||
| Build for production: | ||
|
|
||
| ```sh | ||
| pnpm build | ||
| ``` | ||
|
|
||
| ## About This Example | ||
|
|
||
| This example demonstrates: | ||
|
|
||
| - Descope authentication via the hosted `sign-up-or-in` flow (`<Descope flowId="sign-up-or-in" />`) | ||
| - Self-service account management via the `<UserProfile />` widget (name, avatar, passkeys, MFA) | ||
| - Server-side session validation during SSR with `@descope/node-sdk`, wired through TanStack Start request middleware | ||
| - Protected routes guarded in `beforeLoad` | ||
| - User session management (login, logout, session refresh) | ||
|
|
||
| ### How it works | ||
|
|
||
| The Descope integration lives in `src/integrations/descope/`: | ||
|
|
||
| - **`provider.tsx`** — a client `<DescopeProvider>` wrapping `<AuthProvider>` from `@descope/react-sdk`. Passing `sessionTokenViaCookie` stores the session token in a cookie so it is sent with the SSR document request (rather than living only in local storage). Used in `src/routes/__root.tsx`. | ||
| - **`middleware.ts`** — `descopeMiddleware()`, registered in `src/start.ts` as a TanStack Start `requestMiddleware`. It runs on every server request, validates/refreshes the session, and puts the user on the global start context. | ||
| - **`session.server.ts`** — the server-only logic: reads the `DS` (session) and `DSR` (refresh) cookies, calls `validateAndRefreshSession`, and persists a rotated session cookie. This is the only module that imports `@descope/node-sdk`. | ||
| - **`server.ts`** — a `getSession` server function that reads the user off the global context (works during SSR and client-side navigation). The root route's `beforeLoad` exposes it as `context.user`. | ||
|
|
||
| Routes: | ||
|
|
||
| - **Login** — `src/routes/login.tsx` renders the `<Descope>` flow component. On success it invalidates the router so the server re-reads the new session. | ||
| - **Protected routes** — `src/routes/_authed.tsx` redirects to `/login` when there is no `context.user`; `src/routes/_authed/profile.tsx` renders the Descope `<UserProfile />` widget (every project ships a default `user-profile-widget`) and shows the resolved session. | ||
| - **Logout** — `src/routes/logout.tsx` calls `useDescope().logout()` and clears the server cookies. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| { | ||
| "name": "tanstack-start-example-descope", | ||
| "private": true, | ||
| "main": "index.js", | ||
| "type": "module", | ||
| "scripts": { | ||
| "dev": "vite dev", | ||
| "build": "vite build && tsc --noEmit", | ||
| "preview": "vite preview", | ||
| "start": "pnpx srvx --prod -s ../client dist/server/server.js" | ||
| }, | ||
| "keywords": [], | ||
| "author": "", | ||
| "license": "MIT", | ||
| "dependencies": { | ||
| "@descope/node-sdk": "^2.12.0", | ||
| "@descope/react-sdk": "^2.30.3", | ||
| "@tanstack/react-router": "^1.170.17", | ||
| "@tanstack/react-router-devtools": "^1.167.0", | ||
| "@tanstack/react-start": "^1.168.27", | ||
| "react": "^19.0.0", | ||
| "react-dom": "^19.0.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@tailwindcss/vite": "^4.2.2", | ||
| "@types/react": "^19.0.8", | ||
| "@types/react-dom": "^19.0.3", | ||
| "@vitejs/plugin-react": "^6.0.1", | ||
| "tailwindcss": "^4.2.2", | ||
| "typescript": "^6.0.2", | ||
| "vite": "^8.0.14" | ||
| } | ||
| } | ||
51 changes: 51 additions & 0 deletions
51
examples/react/start-descope/src/components/DefaultCatchBoundary.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import { | ||
| ErrorComponent, | ||
| Link, | ||
| useLocation, | ||
| useRouter, | ||
| } from '@tanstack/react-router' | ||
| import type { ErrorComponentProps } from '@tanstack/react-router' | ||
|
|
||
| export function DefaultCatchBoundary({ error }: ErrorComponentProps) { | ||
| const router = useRouter() | ||
| const isRoot = useLocation({ | ||
| select: (location) => location.pathname === '/', | ||
| }) | ||
|
|
||
| console.error(error) | ||
|
|
||
| return ( | ||
| <div className="min-w-0 flex-1 p-4 flex flex-col items-center justify-center gap-6"> | ||
| <ErrorComponent error={error} /> | ||
| <div className="flex gap-2 items-center flex-wrap"> | ||
| <button | ||
| onClick={() => { | ||
| router.invalidate() | ||
| }} | ||
| className={`px-2 py-1 bg-gray-600 dark:bg-gray-700 rounded-sm text-white uppercase font-extrabold`} | ||
| > | ||
| Try Again | ||
| </button> | ||
| {isRoot ? ( | ||
| <Link | ||
| to="/" | ||
| className={`px-2 py-1 bg-gray-600 dark:bg-gray-700 rounded-sm text-white uppercase font-extrabold`} | ||
| > | ||
| Home | ||
| </Link> | ||
| ) : ( | ||
| <Link | ||
| to="/" | ||
| className={`px-2 py-1 bg-gray-600 dark:bg-gray-700 rounded-sm text-white uppercase font-extrabold`} | ||
| onClick={(e) => { | ||
| e.preventDefault() | ||
| window.history.back() | ||
| }} | ||
| > | ||
| Go Back | ||
| </Link> | ||
| )} | ||
| </div> | ||
| </div> | ||
| ) | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Version mismatch between
@tanstack/react-routerand@tanstack/react-router-devtools.@tanstack/react-routeris at^1.170.17while@tanstack/react-router-devtoolsis at^1.167.0. The devtools package should track the same minor version as the router to avoid API incompatibilities. With^ranges, the devtools could resolve to a version several minors behind the router.🔧 Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents