Convex workos skill
Skill PolarCoding85/convex-agent-skillz/.claude/skills/convex-workos-skill
Claude Code skills for Convex backend development. Drop-in knowledge for queries, mutations, AI agents, components, and auth patterns. Community contributions welcome!
npx -y skills add PolarCoding85/convex-agent-skillz --skill convex-workos-skillAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 17 stars17 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
WorkOS AuthKit authentication integration for Convex. Use when setting up WorkOS AuthKit, configuring ConvexProviderWithAuthKit, handling auto-provisioning, or troubleshooting WorkOS-specific auth issues.
SKILL.md
7.5 KB, as published. Nobody here has run it
Convex + WorkOS AuthKit
Provider-specific patterns for integrating WorkOS AuthKit with Convex.
Required Configuration
1. auth.config.ts
// convex/auth.config.ts
const clientId = process.env.WORKOS_CLIENT_ID;
export default {
providers: [
{
type: 'customJwt',
issuer: 'https://api.workos.com/',
algorithm: 'RS256',
applicationID: clientId,
jwks: `https://api.workos.com/sso/jwks/${clientId}`
},
{
type: 'customJwt',
issuer: `https://api.workos.com/user_management/${clientId}`,
algorithm: 'RS256',
jwks: `https://api.workos.com/sso/jwks/${clientId}`
}
]
};
Note: WorkOS requires TWO provider entries for different JWT issuers.
2. Environment Variables
# .env.local (Vite/React)
VITE_WORKOS_CLIENT_ID=client_01...
VITE_WORKOS_REDIRECT_URI=http://localhost:5173/callback
# .env.local (Next.js)
WORKOS_CLIENT_ID=client_01...
WORKOS_API_KEY=sk_test_...
WORKOS_COOKIE_PASSWORD=your_32_char_minimum_password_here
NEXT_PUBLIC_WORKOS_REDIRECT_URI=http://localhost:3000/callback
# Convex Dashboard Environment Variables
WORKOS_CLIENT_ID=client_01...
Client Setup
React (Vite)
// src/main.tsx
import { AuthKitProvider, useAuth } from "@workos-inc/authkit-react";
import { ConvexProviderWithAuthKit } from "@convex-dev/workos";
import { ConvexReactClient } from "convex/react";
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);
ReactDOM.createRoot(document.getElementById("root")!).render(
<AuthKitProvider
clientId={import.meta.env.VITE_WORKOS_CLIENT_ID}
redirectUri={import.meta.env.VITE_WORKOS_REDIRECT_URI}
>
<ConvexProviderWithAuthKit client={convex} useAuth={useAuth}>
<App />
</ConvexProviderWithAuthKit>
</AuthKitProvider>
);
Install: npm install @workos-inc/authkit-react @convex-dev/workos
Next.js App Router
// components/ConvexClientProvider.tsx
'use client';
import { ReactNode, useCallback, useRef } from 'react';
import { ConvexReactClient, ConvexProviderWithAuth } from 'convex/react';
import { AuthKitProvider, useAuth, useAccessToken } from '@workos-inc/authkit-nextjs/components';
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
export function ConvexClientProvider({ children }: { children: ReactNode }) {
return (
<AuthKitProvider>
<ConvexProviderWithAuth client={convex} useAuth={useAuthFromAuthKit}>
{children}
</ConvexProviderWithAuth>
</AuthKitProvider>
);
}
function useAuthFromAuthKit() {
const { user, loading: isLoading } = useAuth();
const { accessToken, loading: tokenLoading, error: tokenError } = useAccessToken();
const loading = (isLoading ?? false) || (tokenLoading ?? false);
const authenticated = !!user && !!accessToken && !loading;
const stableAccessToken = useRef<string | null>(null);
if (accessToken && !tokenError) {
stableAccessToken.current = accessToken;
}
const fetchAccessToken = useCallback(async () => {
if (stableAccessToken.current && !tokenError) {
return stableAccessToken.current;
}
return null;
}, [tokenError]);
return {
isLoading: loading,
isAuthenticated: authenticated,
fetchAccessToken,
};
}
Install: npm install @workos-inc/authkit-nextjs @convex-dev/workos
Next.js Middleware
// middleware.ts
import { authkitMiddleware } from '@workos-inc/authkit-nextjs';
export default authkitMiddleware({
middlewareAuth: {
enabled: true,
unauthenticatedPaths: ['/', '/sign-in', '/sign-up']
}
});
export const config = {
matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)']
};
Next.js Auth Routes
// app/callback/route.ts
import { handleAuth } from '@workos-inc/authkit-nextjs';
export const GET = handleAuth();
// app/sign-in/route.ts
import { redirect } from 'next/navigation';
import { getSignInUrl } from '@workos-inc/authkit-nextjs';
export async function GET() {
return redirect(await getSignInUrl());
}
// app/sign-up/route.ts
import { redirect } from 'next/navigation';
import { getSignUpUrl } from '@workos-inc/authkit-nextjs';
export async function GET() {
return redirect(await getSignUpUrl());
}
CORS Configuration (React/Vite only)
For React apps, configure CORS in WorkOS Dashboard:
- Authentication > Sessions > Cross-Origin Resource Sharing (CORS)
- Click Manage
- Add your dev domain:
http://localhost:5173 - Add your prod domain when deploying
UI Components
import { useAuth } from "@workos-inc/authkit-react"; // or authkit-nextjs/components
import { Authenticated, Unauthenticated } from "convex/react";
function App() {
const { user, signIn, signOut } = useAuth();
return (
<>
<Authenticated>
<button onClick={() => signOut()}>Sign out</button>
<Content />
</Authenticated>
<Unauthenticated>
<button onClick={() => signIn()}>Sign in</button>
</Unauthenticated>
</>
);
}
Auto-Provisioning (Development)
Convex can auto-create WorkOS environments for development:
- Run template:
npm create convex@latest -- -t react-vite-authkit - Follow prompts to link Convex team with WorkOS
- Dev deployments auto-provision WorkOS environments
Configured automatically:
- Redirect URI
- CORS origin
- Local environment variables in
.env.local
Limitations:
- Only works for dev deployments
- Production must be manually configured
Dev vs Prod Configuration
| Environment | API Key | Redirect URI |
|---|---|---|
| Development | sk_test_... | http://localhost:3000/callback |
| Production | sk_live_... | https://your-domain.com/callback |
Set different WORKOS_CLIENT_ID in Convex Dashboard for dev vs prod deployments.
WorkOS-Specific Troubleshooting
| Issue | Cause | Fix |
|---|---|---|
| CORS error | Domain not added | Add domain in WorkOS Dashboard > Sessions > CORS |
| Token validation fails | Wrong issuer | Check BOTH providers in auth.config.ts |
Missing aud claim | JWT config | Check WorkOS JWT configuration |
| "Platform not authorized" | Workspace unlinked | Run npx convex integration workos disconnect-team then provision-team |
"Platform not authorized" Error
npx convex integration workos disconnect-team
npx convex integration workos provision-team
Note: Use a different email if creating new WorkOS workspace.
DO ✅
- Include BOTH provider entries in auth.config.ts (different issuers)
- Configure CORS for React/Vite apps
- Use
useConvexAuth()not WorkOS'suseAuth()for auth state - Set WORKOS_CLIENT_ID in Convex Dashboard
- Use 32+ char WORKOS_COOKIE_PASSWORD for Next.js
DON'T ❌
- Forget the second provider entry (user_management issuer)
- Skip CORS configuration for browser-based apps
- Use WorkOS auth hooks to gate Convex queries
- Hardcode the client ID (use env var)
- Use same WorkOS env for dev and prod