wobsoriano/elysia-clerk

[Bug] `store.auth` is always `null` in following `derive()`

Closed this issue · 0 comments

EDIT: I didn't read Elysia's docs properly - the derive method is run in the onTransform hook, which itself runs before the onBefore hook (used in elysia-clerk).
TLDR: I shouldn't use derive but onBeforeHandle instead.


Hey, I'm running into a weird issue: anytime I try to use the value auth set in the global store provided by Elysia its value is null, but when I use methods exposed by the plugin I'm able to get result of the toAuth() method without any issue.

I'm trying to use this plugin inside a custom hook I'm working on (which basically merges the Clerk auth and a custom API auth system).

⚠️ Using the plugin "directly" (= without the custom hook) seems to work fine!

Here's the code implementation of my hook:

import { Elysia } from "elysia";
import { clerkClient, clerkPlugin } from "elysia-clerk";

export const unifiedAuthPlugin = () => {
  return new Elysia()
    .use(
      clerkPlugin({
        secretKey: process.env.CLERK_SECRET_KEY,
        publishableKey: process.env.CLERK_PUBLISHABLE_KEY,
      })
    )
    .derive(
      async ({
        store,
        set,
        headers,
        request,
      }) => {
        try {
          console.log("store", store.auth); // This returns `null`

          const authStatus = await clerkClient.authenticateRequest({
            request,
          });

          const res = authStatus.toAuth();

          console.log("res", res); // This returns the data which is expected to be provided by the plugin (the user ID and every other user-related fields/methods)

          store.auth = res;

          console.log("store.auth", store.auth); // Works as expected after setting the value from `res`
        } catch (error) {
          console.error("Error occurred while authenticating request:", error)
        }
      }
    );
};

Here's how my custom hook is used:

import { Elysia } from "elysia";
import { unifiedAuthPlugin } from "../../middlewares/unifiedAuth";
import { getUserSettings } from "./service";

export const users = new Elysia({ prefix: "/users" })
  .use(unifiedAuthPlugin())
  .get(
    "/settings",
    ({ store }) => {
      return getUserSettings({ id: store.auth?.userId });
    },
    {
      detail: {
        tags: ["User"],
        description: "Get my settings",
      },
    }
  );

And here's my entry file (index.ts):

import { Elysia } from "elysia";
import { ApiResult } from "./helpers/ApiError";
import { users } from "./resources/users/router";
import swagger from "@elysiajs/swagger";
import cors from "@elysiajs/cors";

const app = new Elysia()
  .use(
    swagger({
      documentation: {
        info: {
          title: "My API",
          version: "1.0.0",
        },
        tags: [
          { name: "User", description: "User endpoints" },
        ],
      },
    })
  )
  .use(cors())
  .get("/", () => {
    const result = new ApiResult(
      { code: 200, message: "Success", error: false },
      { status: "ok" }
    );

    return result;
  })
  .use(users)
  .listen(3000);

My "hotfix" for now is to just manually authenticate the request with the exposed methods.