Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do you use Clerk with tRPC successfully? #1702

Closed
tmcw opened this issue Sep 11, 2023 · 17 comments
Closed

How do you use Clerk with tRPC successfully? #1702

tmcw opened this issue Sep 11, 2023 · 17 comments
Assignees
Labels
prioritized This issue has been triaged and the team is working on it remix

Comments

@tmcw
Copy link

tmcw commented Sep 11, 2023

We've been using Clerk with tRPC and Remix. So our application makes requests to tRPC in the usual way, and I try get get auth like this:

import { getAuth } from "@clerk/remix/ssr.server.js";
import { FetchCreateContextFnOptions } from "@trpc/server/adapters/fetch";
import { getUserIdFromAuth } from "app/integrations/clerk.server";

export async function createContext({
  req,
  resHeaders,
}: FetchCreateContextFnOptions) {
  const headers = Object.fromEntries(req.headers.entries());

    const auth = await getAuth({
      request: req,
      context: {},
      params: {},
    });

    let userId: string | null = null;
    if (auth.userId) {
      userId = (await getUserIdFromAuth(auth)) || null;
    }

    return { req, resHeaders, userId };
}

This works at first but is not actually good at all: the getAuth method in Clerk makes a pretty hard assumption that it can throw an error and present an interstitial page. Which in a tRPC context makes no sense - you're doing an API request, and getting back a HTML page instead of JSON isn't going to work.

So, we get crashes in prod and pretty polluted logs. What's the right way to do this? As it is, I don't see how to make Clerk work with tRPC, to get a user's auth from an API request and not break the API endpoint.

@jescalan jescalan added the needs-triage A ticket that needs to be triaged by a team member label Sep 12, 2023
@dimkl dimkl added the remix label Sep 12, 2023
@jescalan jescalan added prioritized This issue has been triaged and the team is working on it and removed needs-triage A ticket that needs to be triaged by a team member labels Sep 25, 2023
@em-jones
Copy link

@tmcw Geniune question as I'm interested in using trpc + clerk for an astro app and I imagine my use would have this same problem:
Why aren't we treating this as a fail-able effect like any other fail-able effect?

  • We're reaching into a space where the total type of the function always includes a failure. How is this any different from a timed-out database request?

Given that this is an issue that's been given priority by the company, I trust that this is a legitimate concern. I'm just trying to understand how this is such a show-stopper.

@tmcw
Copy link
Author

tmcw commented Sep 25, 2023

My understanding so far is that basically Clerk refreshes tokens very often, and it does so - when I'm using Remix - by having a custom loader, returning an interstitial response, which triggers a token refresh. This has problems of its own, but - when I'm using tRPC as well, when a request fails, right now it triggers an interstitial - the tRPC endpoint returns HTML instead of JSON and breaks the site. I could treat that as failable, but that leaves open the question of how the token will get refreshed.

We haven't really found a reliable pattern for using Clerk with tRPC or API routes in general, and I haven't seen one suggested (at least for Remix) anywhere. So like you could let your API routes 400, but they'll continue to 400 and you won't get a token refresh like you should.

@kmkinney
Copy link

I'm also having this issue. Using Next.js + tRPC + clerk

@tmcw
Copy link
Author

tmcw commented Oct 4, 2023

I'm not sure that the prioritized label is much reason for hope, my other issue has been stalled for seven months almost nine ten months going on a year but it's prioritized.

@nikosdouvlis
Copy link
Member

Hello @tmcw, @octoper is looking into the Remix + tRPC integration this week, so we'll be able to share more details soon. We'll be looking into the Nextjs issue right after.

Regarding #1043, I will need to check with the team before I can share details - apologies for that.

@octoper
Copy link
Member

octoper commented Oct 6, 2023

Hello @tmcw I took a look at it, and indeed the getAuth inside the tRPC context throws an error when the interstitial criteria are met, but it doesn't actually return an HTML at that point, instead it's just returns an object so we know that an interstitial page has to be thrown, there you could wrap the getAuth in a try/catch block and handle any errors thrown as the user was not authenticated to avoid all those polluted logs you mentioned, now for the part of how the token will be refresh is up to the rootAuthLoader to handle if an interstitial page has to be thrown.
You can also take a look at a simple example I made on how to use Clerk, tRPC and Remix, you can check it here.

@octoper
Copy link
Member

octoper commented Oct 6, 2023

Hello @kmkinney, I have not checked out yet with Next.js but we have a starter (https://github.com/clerkinc/t3-turbo-and-clerk) that you can take a look in case something is not configured properly in your app.

@octoper
Copy link
Member

octoper commented Nov 15, 2023

Hello! 👋
Please let me know if the suggested solution worked for you or if you have any questions. Your feedback is important to us.
If there is no response within 7 days, we will consider the issue resolved and close it.
Feel free to reopen it or reach out for further assistance.
Thanks! 🚀

@eula01
Copy link

eula01 commented Nov 17, 2023

@octoper this is absoltely not resolved – next app router + trpc + clerk is broken

@merveillevaneck
Copy link

i agree this is not resolved at all, integrating clerk into a next 14 app with the app dir and using trpc throws cryptic errors regularly. right now im getting something in the likes of "cannot reading property of undefined (reading resolve)" . given that there is not description other than "add public routes to middleware.ts its not exactly clear what the issue is or if this is even on the lib side of things. please advise on the trpc + clerk docs :)

@oskarhertzman
Copy link

On our deployed netlify site, we always get getAuth() error when refreshing a page that uses a mutation or query. Those queries only work if you first navigate to another page and then to the page that uses that TRPC functionality, pretty broken:

"trpcState": {
                      "json": {
                          "mutations": [
                          ],
                          "queries": [
                              {
                                  "state": {
                                      "data": null,
                                      "dataUpdateCount": 0,
                                      "dataUpdatedAt": 0,
                                      "error": {
                                          "message": "Clerk: getAuth() was called but Clerk can't detect usage of authMiddleware(). Please ensure the following:\n- authMiddleware() is used in your Next.js Middleware.\n- Your Middleware matcher is configured to match this route or page.\n- If you are using the src directory, make sure the Middleware file is inside of it.\n\nFor more details, see https://clerk.com/docs/quickstarts/get-started-with-nextjs.\n",
                                          "data": {
                                              "code": "INTERNAL_SERVER_ERROR",
                                              "httpStatus": 500
                                          .....

@Elliott-Chong
Copy link

Second this, clerk + app router + trpc is completely broken

The page doesn't load and just keeps refreshing. Also getting random 401 errors even though trpc routes are set to public

@mkcode
Copy link

mkcode commented Dec 13, 2023

I'm about to setup next 14 + clerk + trpc and came across this issue. From what I can tell, there is a working example here for how to setup the TRPC context here: https://github.com/clerk/t3-turbo-and-clerk/blob/main/packages/api/src/context.ts

It seems important to distinguish between the import { auth } from "@clerk/nextjs"; and import { getAuth } from "@clerk/nextjs/server"; as the former does all all sorts of next redirects and such and the latter looks at the headers that should have been already set by the middleware. This also means that it is important to run the clerk middleware on the TRPC endpoint url.

See this file for more: https://github.com/clerk/javascript/blob/main/packages/nextjs/src/server/getAuth.ts

@filipszu
Copy link

Is there any working example of how we can intergate it similair to this example:

https://github.com/clerk/t3-turbo-and-clerk/blob/main/packages/api/src/context.ts

but using the Next JS App Router and publicRoutes in middleware.ts?

@Elliott-Chong
Copy link

Elliott-Chong commented Dec 18, 2023

the publicRoutes option was not working for me, and I could not remove the /api/trpc matcher from the nextjs middleware matcher option.

So I just used the ignoredRoutes options to make some of my trpc endpoints public. It's working for me so far.

import { authMiddleware } from "@clerk/nextjs";

export default authMiddleware({
  publicRoutes: [
    "/api/trpc/public.getOrgInfo(.*)",
    "/",
    "/api/status/change",
    "/api/generatePresignedS3Url(.*)",
    "/application(.*)",
    "/api/agent",
    "/api/conversation",
    "/api/organization",
    "/api/message/ai",
    "/api/message/client",
    "/api/release-conversations",
    "/application/(.*)",
    "/api/trpc/application(.*)",
    "/api/trpc/public(.*)",
  ],
  // ignore /api/trpc/public
  ignoredRoutes: ["/api/trpc/public(.*)"],
});

export const config = {
  matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};

@mkcode
Copy link

mkcode commented Dec 20, 2023

Hi All, I got this working smoothly in my application. I created a gist with the basics of how to do it: https://gist.github.com/mkcode/a590d1c8f7b0a37b8299965de7f7e958

@anagstef anagstef self-assigned this May 27, 2024
@anagstef
Copy link
Member

Hello and thank you all for your patience. The interstitial mechanism in previous versions was indeed causing issues like the ones you've described. To address this, we have completely replaced it in our latest Core 2 release with a new mechanism to mitigate such issues.

We advise updating to the latest major versions: either @clerk/remix@4 or @clerk/nextjs@5.

How to upgrade Remix to Core 2: https://clerk.com/docs/upgrade-guides/core-2/remix
How to upgrade Nextjs to Core 2: https://clerk.com/docs/upgrade-guides/core-2/nextjs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
prioritized This issue has been triaged and the team is working on it remix
Projects
None yet
Development

No branches or pull requests