clerk / javascript

Official JavaScript repository for Clerk authentication
https://clerk.com
MIT License
1.14k stars 259 forks source link

If custom "aud" claim is added to session token, getAuth() fails in getServerSideProps #1507

Closed Richard87 closed 1 year ago

Richard87 commented 1 year ago

Frontend API: pk_test_cGVyZmVjdC1nb3JpbGxhLTk4LmNsZXJrLmFjY291bnRzLmRldiQ

Package + Version

Dependencies + versions

Provide a json with the dependencies used in your project (copy paste from yarn.lock / package-lock.json) or a github project / template that reproduces the issue.

*Include the @clerk/ packages and their versions!**

Example:

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "storybook": "storybook dev -p 6006",
    "build-storybook": "storybook build"
  },
  "dependencies": {
    "@clerk/nextjs": "^4.19.1",
    "@clerk/types": "^3.43.0",
    "@emotion/react": "^11.11.1",
    "@emotion/styled": "^11.11.0",
    "@mui/icons-material": "^5.11.16",
    "@mui/material": "^5.13.4",
    "@zodios/react": "^10.4.5",
    "axios": "^1.4.0",
    "next": "13.4.2",
    "notistack": "^3.0.1",
    "react": "18.2.0",
    "react-cookie": "^4.1.1",
    "react-dom": "18.2.0",
    "@tanstack/react-query": "^4.29.25",
    "react-responsive": "^9.0.2",
    "styled-components": "^6.0.0-rc.3",
    "validator": "^13.9.0",
    "yarn": "^1.22.19"
  },
  "devDependencies": {
    "@storybook/addon-essentials": "^7.0.23",
    "@storybook/addon-interactions": "^7.0.23",
    "@storybook/addon-links": "^7.0.23",
    "@storybook/blocks": "^7.0.23",
    "@storybook/nextjs": "^7.0.23",
    "@storybook/react": "^7.0.23",
    "@storybook/testing-library": "^0.0.14-next.2",
    "@types/react": "18.2.6",
    "@typescript-eslint/eslint-plugin": "^5.59.7",
    "@typescript-eslint/parser": "^5.59.7",
    "eslint": "^8.40.0",
    "eslint-config-next": "13.4.2",
    "eslint-plugin-storybook": "^0.6.12",
    "openapi-zod-client": "^1.9.0",
    "storybook": "^7.0.23",
    "typescript": "^5.0.4"
  }
}

Browser/OS

Chrome: Versjon 114.0.5735.198 (Offisiell delversjon) (arm64) Node: v16.20.1 Cloudflare worker: no idea how to check

Description

When a custom "aud" claim is added to the session token: Invalid JWT audience claim (aud) \"http://localhost:3000\". Expected \"undefined\". Make sure that this is a valid Clerk generate JWT. (reason=token-verification-failed, token-carrier=cookie)",

-- Added x-clerk-debug on request

Clerk debug start :: getAuth()
-- Headers debug, {
  "authStatus": "signed-out",
  "authMessage": "Invalid JWT audience claim (aud) \"http://localhost:3000\". Expected \"undefined\". Make sure that this is a valid Clerk generate JWT. (reason=token-verification-failed, token-carrier=cookie)",
  "authReason": "token-verification-failed"
}
-- Options debug, {
  "apiKey": "",
  "secretKey": "sk_test_*********jjg",
  "apiUrl": "https://api.clerk.dev",
  "apiVersion": "v1",
  "authStatus": "signed-out",
  "authMessage": "Invalid JWT audience claim (aud) \"http://localhost:3000\". Expected \"undefined\". Make sure that this is a valid Clerk generate JWT. (reason=token-verification-failed, token-carrier=cookie)",
  "authReason": "token-verification-failed"
}

null

My pages/minside/test file: Note: This works great without the custom aud, but its required for the backend api

import {buildClerkProps, clerkClient, getAuth} from "@clerk/nextjs/server";
import {SignInButton} from "@clerk/nextjs";

export const getServerSideProps = async (ctx) => {
const {userId} = getAuth(ctx.req, {secretKey: process.env.CLERK_SECRET_KEY});
    if (!userId) {
    return {
      redirect: {
        destination: "/",
        permanent: false,
      },
    };
  }

  const user = await clerkClient.users.getUser(userId);
  const memberId = user?.publicMetadata?.member_id ?? null;
  const roles = user?.publicMetadata?.roles ?? [];

  return { props: { ...buildClerkProps(ctx.req),userId, memberId, roles } };
}

export default function Test(props) {

  console.log(props)

  return (
    <div>
      <SignInButton mode={"modal"} />
      <h1>Test</h1>
    </div>
  )
}

My pages/_app.tsx file:

import { ClerkProvider } from "@clerk/nextjs";
import type { AppProps } from "next/app";
import { SnackbarProvider } from "notistack";
import {Theme} from "../components/Theme";
import "../styles/globals.css";
import {QueryClientProvider, QueryClient} from "@tanstack/react-query";

const queryClient = new QueryClient();

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <SnackbarProvider maxSnack={2}>
      <QueryClientProvider client={queryClient}>
        <Theme>
          <ClerkProvider {...pageProps}>
            <Component {...pageProps} />
          </ClerkProvider>
        </Theme>
      </QueryClientProvider>
    </SnackbarProvider>
  );
}

export default MyApp;

And my middleware.ts file:

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

export default authMiddleware({
  publicRoutes: ["/(.*)"],
  debug: true,

});

export const config = {
  matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api|trpc)(.*)"],
};
dimkl commented 1 year ago

Hello @Richard87 and thank you for the feedback. Based on the package.json you provided, you are using @clerk/nextjs@4.19.x. The support of @clerk/nextjs@4.21.0. I would suggest you upgrade.

Also based on your snippets and the error message it seems that even though the aud claim exists in the session token, you don't provide an audience parameter to validate against it in your backend. To support the audience verification you should pass an audience?: string | string[]; parameter to authMiddleware() with the allowed audiences.

Could you take a look at the above and let me know if your issue is resolved?

Some extra notes:

Richard87 commented 1 year ago

When upgrading to Next 13.4.0 to 13.4.12 I get this error when using getServersideProps... So no idea whats going on there! Will open a issue on MUI and see if they have any idea...

https://github.com/mui/material-ui/issues/38177

Skjermbilde 2023-07-26 kl  22 17 33
Richard87 commented 1 year ago

@dimkl Thanks for helping out, will useUser or useSession also trigger request rate limits? I see they both also include the User object?

Is there a way to get the current session token/claims without useUser/useSession?

dimkl commented 1 year ago

@Richard87 I believe that useSession / useUser are client-side components, where there aren't request rate limits since those requests are triggered by the Browser of the end-user. The request rate limits (I mentioned in my previous) comment are related to the request to server-to-server requests between your server and Clerk backend API.

Do you need the current session token/claims in the server?

Richard87 commented 1 year ago

Hi, @dimkl , thanks thats what I need to know! I have roles and member_id in public metadata, also in the session token, but as long as I can use useUser / useSession I'm good to go!

When I upgraded Clerk and added audience to the middleware the error went away! Thank you for the assistance :)

clerk-cookie commented 3 months ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.