Andy Vennells
Andy Vennells

Reputation: 307

Configuring NextJs (T3 create) App router to use Auth0

I have just started rebuilding a NextJs app using npm create t3 latest. I've selected typescript, trcp tailwind and prisma ORM.

I don't want to use NextAuth because I have everything I need in Auth0 and NextAuth seems to have limitations.

I did downgrade NextJs from 15.0.3 to 14.2.5 because I was getting an error and I am building this app based on an existing, poorly structured app which was using version 14.2.5.

T3 configures the page with the App router and I am trying to configure auth0 to work with my T3 created app.

I have followed instructions on both of these links (both very similar):

https://developer.auth0.com/resources/guides/web-app/nextjs/basic-authentication https://auth0.com/docs/quickstart/webapp/nextjs/interactive

But I have 2 problems which I have been trying to fix for far too long:

Issue 1: unable to get use data after they have logged in

Acording to documentation, I should be able to conditinally render componenets based on if the user exists in the session (show login/logout button for example).

I am trying to get the user data via getSession for server side components and useUser for client side componenets but they return null and undefined respectively even after the user has logged in. I am using a dynamic route for one of my pages.

I've also tried logging out using the OIDC endpoint using the link below, but you need the token or session id issued to the user, which I'm unable to retrieve (followed these instructions:

If I use await getAccessToken() I get this error: AccessTokenError: The user does not have a valid session. at Object.getAccessToken

I have added the <UserProvider>{children}</UserProvider> to my layout.

Issue 2: The login session persists, even when the user logs out If the user logs out, they should have to enter their credentials again before logging back in. This doesn't happen and if the user clicks the logout button, then clicks login again, they are sent straight back to the site. This seems like a security breach to me.

I've also followed this page with the same issue but none of these solutions work for me either: https://auth0.com/docs/authenticate/login/logout/log-users-out-of-auth0:

Here are my files:

src/app/layout.tsx*

import "@/styles/globals.css";

import { GeistSans } from "geist/font/sans";
import { type Metadata } from "next";

import { TRPCReactProvider } from "@/trpc/react";
import { UserProvider } from "@auth0/nextjs-auth0/client";

export const metadata: Metadata = {
  title: "Title",
  description: "Description",
  icons: [{ rel: "icon", url: "/favicon.ico" }],
};

export default async function RootLayout({
  children,
}: Readonly<{ children: React.ReactNode }>) {

 
  return (
    <html lang="en" className={`${GeistSans.variable}`}>
      <body>
      <UserProvider>
        {/* <TRPCReactProvider> */}
          {children}
        {/* </TRPCReactProvider> */}
        </UserProvider>
      </body>
    </html>
  );
}

src/app/user/[step]/page.tsx

import LoginButtons from "@/app/components/loginButtons";
import SignOut from "@/app/components/signOut";
import { getAccessToken } from "@auth0/nextjs-auth0";
import Test from "@/app/components/test";

const Step = async ({ params }: { params: { step: string } }) => {
  
  const { accessToken } = await getAccessToken();

  console.log("Access Token in Step", accessToken);

if (!params.step) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>Step {params.step}</h1>
      <p>This is the {params.step} step</p>
      {/* <UserProvider> */}
        {/* <LoginButtons /> */}
        <SignOut />
        <Test />
      {/* </UserProvider> */}
    </div>
  );
}

// export default Step;
export default Step;

app/components/loginButtons.tsx

import React from "react";
import { getSession } from "@auth0/nextjs-auth0";

export default async function LoginButtons() {
    const user  = await getSession();

    console.log("log user in buttons component", user);

    // if (isLoading)
    //     return (<div>Loading...</div>);

    // if (error) {
    //     // console.error("Error fetching user:", error);
    //     return (<div>Oops... {error.message} STACK = {error?.stack} user = {user ? user.name : "undefined"}</div>);
    // }

    return (
        <main className="flex justify-between">
            <div className="w-dvw min-h-dvh h-full items-center text-sm grid grid-cols-3 bg-main">
                {user && (<a href={"/api/auth/logout"} >Logout</a>)}
                {!user && (
                    <>
                        <a href="/api/auth/login">Login</a>
                        <a href="/api/auth/signup">SignUp</a>
                        <a href={"/api/auth/logout"} >Logout</a>
                    </>
                )}
            </div>
        </main>
    )
}

app/componenets/test/tsx - test to show client side component and useUser()

"use client";

import { useUser } from "@auth0/nextjs-auth0/client";

export default function Test() {
  const { user } = useUser();
  console.log("Log user in test client component", user);

  return (
        <div>
          user: <pre>{JSON.stringify(user, null, 2)}</pre>
        </div>
  );
}

package.json

{
  "name": "gothrive.app",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "@snaplet/seed": {
    "config": "prisma\\seed\\seed.config.ts"
  },
  "scripts": {
    "build": "next build",
    "check": "next lint && tsc --noEmit",
    "db:generate": "prisma migrate dev",
    "db:migrate": "prisma migrate deploy",
    "db:push": "prisma db push",
    "db:studio": "prisma studio",
    "dev": "next dev --turbo",
    "format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,mdx}\" --cache",
    "format:write": "prettier --write \"**/*.{ts,tsx,js,jsx,mdx}\" --cache",
    "postinstall": "prisma generate",
    "lint": "next lint",
    "lint:fix": "next lint --fix",
    "preview": "next build && next start",
    "start": "next start",
    "typecheck": "tsc --noEmit",
    "test:watch": "jest --watchAll",
    "test:integration": "yarn docker:up && yarn prisma migrate deploy && jest -i",
    "docker:up": "docker compose up -d",
    "docker:down": "docker compose down",
    "test": "yarn docker:up && yarn prisma migrate deploy && jest -i",
    "postmigrate": "npx @snaplet/seed sync",
    "seed": "prisma db seed",
    "storybook": "storybook dev -p 6006",
    "build-storybook": "storybook build"
  },
  "dependencies": {
    "@auth0/nextjs-auth0": "^3.5.0",
    "@prisma/client": "^5.14.0",
    "@t3-oss/env-nextjs": "^0.10.1",
    "@tanstack/react-query": "^5.50.0",
    "@trpc/client": "^11.0.0-rc.446",
    "@trpc/react-query": "^11.0.0-rc.446",
    "@trpc/server": "^11.0.0-rc.446",
    "geist": "^1.3.0",
    "next": "14.2.5",
    "prisma-field-encryption": "^1.6.0",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "server-only": "^0.0.1",
    "snaplet": "^0.42.1",
    "superjson": "^2.2.1",
    "tsx": "^4.19.2",
    "zod": "^3.23.3"
  },
  "devDependencies": {
    "@chromatic-com/storybook": "3.2.2",
    "@storybook/addon-essentials": "8.4.5",
    "@storybook/addon-interactions": "8.4.5",
    "@storybook/addon-onboarding": "8.4.5",
    "@storybook/blocks": "8.4.5",
    "@storybook/nextjs": "8.4.5",
    "@storybook/react": "8.4.5",
    "@storybook/test": "8.4.5",
    "@types/eslint": "^8.56.10",
    "@types/node": "^20.14.10",
    "@types/react": "^18.3.3",
    "@types/react-dom": "^18.3.0",
    "@typescript-eslint/eslint-plugin": "^8.1.0",
    "@typescript-eslint/parser": "^8.1.0",
    "eslint": "^8.57.0",
    "eslint-config-next": "^15.0.1",
    "eslint-plugin-storybook": "^0.11.1",
    "postcss": "^8.4.39",
    "prettier": "^3.3.2",
    "prettier-plugin-tailwindcss": "^0.6.5",
    "prisma": "^5.14.0",
    "storybook": "8.4.5",
    "tailwindcss": "^3.4.3",
    "typescript": "^5.5.3"
  },
  "ct3aMetadata": {
    "initVersion": "7.38.1"
  }
}

Upvotes: 0

Views: 118

Answers (1)

Andy Vennells
Andy Vennells

Reputation: 307

Hi found the answer here:

https://community.auth0.com/t/error-in-nextjs-15/151480

The answer was to upgrade again back to NextJs V15.0.3 following this:

https://www.npmjs.com/package/@auth0/nextjs-auth0/v/4.0.0-beta.0

it might sound silly that I downgraded to NextJs 14, but I have been using Auth0 with NextJs for a while using the dynamic API approach and when i downgraded, I compared the package.json with another working project. It seemed like a good idea to take that approach. After posting this and stepping back, i decided to try fixing the errors in NextJs v15 which has a different aproach to the dynamic API approach explained in the link above. Once I had that working, both of my issues were resolved.

Upvotes: 0

Related Questions