#auth
9 messages · Page 1 of 1 (latest)
Hi @viscid elm. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
To access the authenticated WorkOS AuthKit user inside a Convex function, you use Convex’s built‑in auth API: ctx.auth.getUserIdentity().
1. Make sure AuthKit is wired to Convex
On the client, wrap your app with AuthKitProvider and ConvexProviderWithAuthKit (or ConvexProviderWithAuth + a custom useAuth), so Convex receives the WorkOS token:
import { AuthKitProvider, useAuth } from "@workos-inc/authkit-react";
import { ConvexReactClient } from "convex/react";
import { ConvexProviderWithAuthKit } from "@convex-dev/workos";
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);
<AuthKitProvider
clientId={import.meta.env.VITE_WORKOS_CLIENT_ID}
redirectUri={import.meta.env.VITE_WORKOS_REDIRECT_URI}
>
<ConvexProviderWithAuthKit client={convex} useAuth={useAuth}>
{/* your app */}
</ConvexProviderWithAuthKit>
</AuthKitProvider>
```[[AuthKit React](<https://docs.convex.dev/auth/authkit/#react>)]
On the Convex side, configure `auth.config.ts` for WorkOS AuthKit:
```ts
// convex/auth.config.ts
const clientId = process.env.WORKOS_CLIENT_ID;
const authConfig = {
providers: [
{
type: "customJwt",
issuer: `<https://api.workos.com/`,>
algorithm: "RS256",
jwks: `<https://api.workos.com/sso/jwks/${clientId}`,>
applicationID: clientId,
},
{
type: "customJwt",
issuer: `<https://api.workos.com/user_management/${clientId}`,>
algorithm: "RS256",
jwks: `<https://api.workos.com/sso/jwks/${clientId}`,>
// NOTE: intentionally no applicationID here (see Discord workaround)
},
],
};
export default authConfig;
```[[AuthKit config](<https://docs.convex.dev/auth/authkit/#client-configuration>)]
If you see ctx.auth.getUserIdentity() returning null even when logged in, one known workaround is to omit applicationID on the second provider, as mentioned in the Discord thread.[Discord thread]
2. Use ctx.auth.getUserIdentity() in your Convex function
In any query/mutation/action:
// convex/myFunctions.ts
import { query } from "./_generated/server";
export const currentViewer = query({
args: {},
handler: async (ctx) => {
const identity = await ctx.auth.getUserIdentity();
if (identity === null) {
throw new Error("Not authenticated");
}
// identity contains tokenIdentifier, subject, issuer, and any claims
// WorkOS put into the JWT (e.g. name, email, org_id if configured).
return {
subject: identity.subject,
issuer: identity.issuer,
tokenIdentifier: identity.tokenIdentifier,
// Example of accessing a custom claim if you added it:
// orgId: (identity as any)["org_id"],
};
},
});
```[[Auth in functions](<https://docs.convex.dev/auth/functions-auth>); [Auth interface](<https://docs.convex.dev/api/interfaces/server.Auth>)]
Make sure the client component calling this function is rendered under `<Authenticated>` from `convex/react`, so Convex has a validated token before the query runs:
```tsx
import { Authenticated, Unauthenticated } from "convex/react";
<Authenticated>
{/* components that call authenticated Convex functions */}
</Authenticated>
<Unauthenticated>
<p>Please sign in to view data</p>
</Unauthenticated>
```[[AuthKit React](<https://docs.convex.dev/auth/authkit/#react>)]
### 3. Getting richer user data (optional)
If you also install the `@convex-dev/workos-authkit` component, you can get a fully synced WorkOS user document (not just raw JWT claims) via:
// convex/auth.ts
import { AuthKit } from "@convex-dev/workos-authkit";
import { components } from "./_generated/api";
import type { DataModel } from "./_generated/dataModel";
export const authKit = new AuthKit<DataModel>(components.workOSAuthKit);
Then in a function:
import { query } from "./_generated/server";
import { authKit } from "./auth";
export const getCurrentUser = query({
args: {},
handler: async (ctx) => {
const user = await authKit.getAuthUser(ctx);
return user; // Convex user record synced from WorkOS
},
});
```[[WorkOS component](<https://www.convex.dev/components/workos-authkit>)]
If something still returns `null`, double‑check:
- You’re signed in via AuthKit on the client.
- The calling component is under `<Authenticated>`.
- `WORKOS_CLIENT_ID` is set in Convex and matches your WorkOS environment.
- The second provider in `auth.config.ts` does **not** specify `applicationID` (per the Discord workaround).
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@viscid elm Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@spark aurora cant i use ctx.auth.getUserIdentity
Let me check the knowledge base for you again. One moment! :books:
Yes, you can use ctx.auth.getUserIdentity with WorkOS; that’s exactly how Convex exposes the authenticated user in your functions.
In any query/mutation/action:
import { query } from "./_generated/server";
export const myAuthedQuery = query({
args: {},
handler: async (ctx) => {
const identity = await ctx.auth.getUserIdentity();
if (identity === null) {
throw new Error("Unauthenticated call");
}
// identity has tokenIdentifier, subject, issuer, and other claims
return {
subject: identity.subject,
email: identity.email,
name: identity.name,
};
},
});
```[[Auth in functions](<https://docs.convex.dev/auth/functions-auth>)]
Two important requirements:
1. **Client must be authenticated and wired to Convex** (e.g. via `ConvexProviderWithAuthKit` / `ConvexProviderWithAuth` and WorkOS AuthKit), so Convex actually receives a JWT. [[AuthKit React](<https://docs.convex.dev/auth/authkit/#react>)]
2. **The component calling this query must be inside `<Authenticated>` from `convex/react`**, otherwise the query can run before Convex has a validated token and `getUserIdentity()` will return `null`. [[AuthKit React](<https://docs.convex.dev/auth/authkit/#react>); [Debugging auth](<https://docs.convex.dev/auth/debug>)]
If you’re seeing `null` even when logged in, that’s usually due to (2) or misconfigured WorkOS JWT (e.g. `aud` / `applicationID` mismatch); the debug doc walks through how to check this with logs. [[Debugging auth](<https://docs.convex.dev/auth/debug>)]
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------