#authorize inside http actions

1 messages · Page 1 of 1 (latest)

minor rapids
#

what do i have to send with an http request to a http action endpoint, so that ctx.auth.getUserIdentity returns the useridentity?

past sluiceBOT
#

Hi @minor rapids. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

To have ctx.auth.getUserIdentity() return a UserIdentity in an HTTP action, you must send a valid JWT in the Authorization header of the HTTP request.

Request requirement

GET <https://<deployment-name>.convex.site/myAction>
Authorization: Bearer <your-jwt-token>

On the server, your HTTP action can then do:

import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";

const http = httpRouter();

http.route({
  path: "/myAction",
  method: "GET",
  handler: httpAction(async (ctx, request) => {
    const identity = await ctx.auth.getUserIdentity();
    // identity is null if the token is missing/invalid
    // otherwise it's a UserIdentity
    // ...
    return new Response("ok");
  }),
});

export default http;

This pattern—sending Authorization: Bearer <JWT>—is what Convex expects for authenticating HTTP actions so that ctx.auth.getUserIdentity() can resolve to the current user. [Auth in functions; HTTP actions auth]

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@minor rapids Kapa.ai is still learning and improving, please let me know how I did by reacting below.

minor rapids
#

@past sluice how do i access the jwt token on the frontend?

past sluiceBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

To access the JWT token on the frontend, use the Convex Auth React hook useAuthToken and then pass it in the Authorization header when calling your HTTP action.

Example:

import { useAuthToken } from "@convex-dev/auth/react";

function SomeComponent() {
  const token = useAuthToken();

  const onClick = async () => {
    const res = await fetch(`${process.env.VITE_CONVEX_SITE_URL!}/someEndpoint`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });
    // ...
  };

  // ...
}

useAuthToken() returns string | null with the JWT Convex uses for ctx.auth.getUserIdentity() in HTTP actions. [useAuthToken hook; Auth HTTP actions]

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@minor rapids Kapa.ai is still learning and improving, please let me know how I did by reacting below.

minor rapids
#

@past sluice i get an cors error

past sluiceBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

You’re on the right track; when calling Convex HTTP actions from the browser with a custom fetch (e.g. to send the JWT), you must add CORS handling on the Convex side. The CORS error is almost certainly because the HTTP action isn’t returning the right CORS headers and/or isn’t handling the preflight OPTIONS request.

Here are two ways to fix it.


1. Minimal manual CORS setup

In convex/http.ts, add CORS headers to your endpoint and handle OPTIONS for preflight:

import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";

const http = httpRouter();

http.route({
  path: "/someEndpoint",
  method: "POST",
  handler: httpAction(async (ctx, request) => {
    // ... your logic (can use ctx.auth.getUserIdentity()) ...

    return new Response("ok", {
      status: 200,
      headers: new Headers({
        // e.g. <https://your-frontend.com,> or from env
        "Access-Control-Allow-Origin": process.env.CLIENT_ORIGIN!,
        Vary: "origin",
      }),
    });
  }),
});

// Pre-flight for /someEndpoint
http.route({
  path: "/someEndpoint",
  method: "OPTIONS",
  handler: httpAction(async (_, request) => {
    const headers = request.headers;
    if (
      headers.get("Origin") !== null &&
      headers.get("Access-Control-Request-Method") !== null &&
      headers.get("Access-Control-Request-Headers") !== null
    ) {
      return new Response(null, {
        headers: new Headers({
          "Access-Control-Allow-Origin": process.env.CLIENT_ORIGIN!,
          "Access-Control-Allow-Methods": "POST",
          "Access-Control-Allow-Headers": "Content-Type, Authorization",
          "Access-Control-Max-Age": "86400",
        }),
      });
    } else {
      return new Response();
    }
  }),
});

export default http;
#

This is the same pattern Convex uses for file upload HTTP actions and general CORS examples. [HTTP CORS example; Upload HTTP action]


2. Use the corsRouter helper (simpler)

If you’re okay adding convex-helpers, you can let it generate the CORS + OPTIONS handling for you:

import { httpRouter } from "convex/server";
import { corsRouter } from "convex-helpers/server/cors";
import { httpAction } from "./_generated/server";

const http = httpRouter();
const cors = corsRouter(http, {
  allowedOrigins: ["<https://your-frontend.com"],> // or "*"
  allowedHeaders: ["Content-Type", "Authorization"],
});

// Your endpoint with CORS support
cors.route({
  path: "/someEndpoint",
  method: "POST",
  handler: httpAction(async (ctx, request) => {
    // ... your logic ...
    return new Response("ok");
  }),
});

export default http;

corsRouter automatically creates the matching OPTIONS route and headers. [CORS helper; Discord CORS helper usage]


Quick checklist

  1. Use .convex.site URL in your fetch, not .convex.cloud. [HTTP debugging]
  2. Ensure your HTTP action:
    • Returns Access-Control-Allow-Origin (and other needed headers) on the actual response.
    • Has an OPTIONS handler (manually or via corsRouter) for preflight.
  3. In the browser devtools Network tab, confirm:
    • An OPTIONS request succeeds (200/204) with CORS headers.
    • The subsequent POST/GET also has Access-Control-Allow-Origin.
#

If you paste your current convex/http.ts and the exact browser error message, I can point out the exact header/route you’re missing.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: