Authentication Documentation
talk.dev uses WorkOS AuthKit for authentication, sharing the same WorkOS organization as do.dev.
Architecture
WorkOS Organization (shared)
├── Single sign-on across do.dev and talk.dev
├── User Management handles all authentication
└── JWT tokens validated via JWKS
talk.dev
├── authkitMiddleware protects routes
├── /sign-in redirects to WorkOS hosted UI
├── /callback handles OAuth response
└── HTTP-only cookies store sessionKey Files
| File | Purpose |
|---|---|
middleware.ts | authkitMiddleware with unauthenticatedPaths |
app/sign-in/[[...sign-in]]/page.tsx | Redirects to WorkOS sign-in |
app/callback/route.ts | OAuth callback handler |
app/sign-out/page.tsx | Sign out and clear session |
lib/use-auth.ts | Client-side auth hook (SWR) |
app/api/auth/user/route.ts | Returns current user |
app/api/auth/desktop-token/route.ts | Returns access token for desktop |
components/convex-client-provider.tsx | Convex auth integration |
Environment Variables
# WorkOS AuthKit Configuration
WORKOS_CLIENT_ID=client_xxx
WORKOS_API_KEY=sk_test_xxx
WORKOS_COOKIE_PASSWORD=<32+ char random string>
NEXT_PUBLIC_WORKOS_REDIRECT_URI=http://localhost:3012/callbackDesktop Authentication Flow
- Desktop app opens
/desktop-authin browser - If not authenticated, redirects to
/sign-in?returnTo=/desktop-auth - User signs in via WorkOS hosted UI
- After auth, redirected back to
/desktop-auth - Page fetches access token from
/api/auth/desktop-token - User clicks button to open
talkdev://auth/callback?data=... - Desktop app receives token via deep link
Convex Integration
Convex validates WorkOS JWTs directly via JWKS:
// convex/auth.config.ts
export default {
providers: [
{
type: "customJwt",
issuer: "https://api.workos.com/",
algorithm: "RS256",
jwks: `https://api.workos.com/sso/jwks/${clientId}`,
},
],
};The identity.subject in Convex functions contains the WorkOS user ID.
Troubleshooting
"Invalid redirect URI" error? → Add the redirect URI to WorkOS Dashboard → Redirects
Session not persisting? → Check WORKOS_COOKIE_PASSWORD is set and at least 32 characters
Desktop auth not redirecting back?
→ Ensure /desktop-auth is in unauthenticatedPaths in middleware