#auth

9 messages · Page 1 of 1 (latest)

viscid elm
#

how to get my workos auth identity in my convex function?

spark auroraBOT
#

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.

viscid elm
#

@spark aurora cant i use ctx.auth.getUserIdentity

spark auroraBOT
#

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:
----------------------