From 3362c987815431420a6cc14646ff7726d0c9b4d6 Mon Sep 17 00:00:00 2001
From: PxlLoewe <72106766+PxlLoewe@users.noreply.github.com>
Date: Tue, 11 Mar 2025 20:07:53 -0700
Subject: [PATCH] Fixed login bug when one app users the jwt of the other
---
apps/dispatch/.env.example | 3 +-
.../app/(auth)/login/_components/Login.tsx | 116 ++++++++-------
.../app/api/auth/[...nextauth]/auth.ts | 134 ++++++++++--------
3 files changed, 137 insertions(+), 116 deletions(-)
diff --git a/apps/dispatch/.env.example b/apps/dispatch/.env.example
index 07d01925..92ef77c0 100644
--- a/apps/dispatch/.env.example
+++ b/apps/dispatch/.env.example
@@ -1,2 +1,3 @@
NEXT_PUBLIC_HUB_URL=
-NEXT_PUBLIC_SERVICE_ID=
\ No newline at end of file
+NEXT_PUBLIC_SERVICE_ID=
+NEXTAUTH_SECRET=
\ No newline at end of file
diff --git a/apps/dispatch/app/(auth)/login/_components/Login.tsx b/apps/dispatch/app/(auth)/login/_components/Login.tsx
index 76e5c388..0e9be153 100644
--- a/apps/dispatch/app/(auth)/login/_components/Login.tsx
+++ b/apps/dispatch/app/(auth)/login/_components/Login.tsx
@@ -1,60 +1,68 @@
-'use client';
-import { signIn } from 'next-auth/react';
-import { useSearchParams } from 'next/navigation';
-import { useEffect, useState } from 'react';
-import { Toaster } from 'react-hot-toast';
+"use client";
+import { signIn, useSession } from "next-auth/react";
+import { useRouter, useSearchParams } from "next/navigation";
+import { useEffect, useState } from "react";
+import { Toaster } from "react-hot-toast";
export const Login = () => {
- const [isLoading, setIsLoading] = useState(false);
- const searchParams = useSearchParams();
+ const [isLoading, setIsLoading] = useState(false);
+ const searchParams = useSearchParams();
+ const { data: session } = useSession();
+ const navigate = useRouter();
- useEffect(() => {
- const signInWithCode = async () => {
- const code = searchParams.get('code');
- if (code) {
- setIsLoading(true);
- await signIn('credentials', {
- code: code,
- callbackUrl: '/',
- });
- setIsLoading(false);
- }
- };
- signInWithCode();
- }, [searchParams]);
+ useEffect(() => {
+ if (session) {
+ navigate.push("/");
+ }
+ }, [session, navigate]);
- return (
-
-
-
-
-
Login
-
- Noch keinen Account? Zur{' '}
-
- Registrierung
-
-
+ useEffect(() => {
+ const signInWithCode = async () => {
+ const code = searchParams.get("code");
+ if (code) {
+ setIsLoading(true);
+ await signIn("credentials", {
+ code: code,
+ callbackUrl: "/",
+ });
+ setIsLoading(false);
+ }
+ };
+ signInWithCode();
+ }, [searchParams]);
-
-
- );
+ return (
+
+ );
};
diff --git a/apps/dispatch/app/api/auth/[...nextauth]/auth.ts b/apps/dispatch/app/api/auth/[...nextauth]/auth.ts
index 17636942..79259789 100644
--- a/apps/dispatch/app/api/auth/[...nextauth]/auth.ts
+++ b/apps/dispatch/app/api/auth/[...nextauth]/auth.ts
@@ -1,70 +1,82 @@
import {
- AuthOptions,
- getServerSession as getNextAuthServerSession,
-} from 'next-auth';
-import { PrismaAdapter } from '@next-auth/prisma-adapter';
-import Credentials from 'next-auth/providers/credentials';
-import { PrismaClient } from '@repo/db';
-const prisma = new PrismaClient();
+ AuthOptions,
+ getServerSession as getNextAuthServerSession,
+} from "next-auth";
+import { PrismaAdapter } from "@next-auth/prisma-adapter";
+import Credentials from "next-auth/providers/credentials";
+import { prisma, PrismaClient } from "@repo/db";
export const options: AuthOptions = {
- providers: [
- Credentials({
- credentials: {
- code: { label: 'code', type: 'code' },
- },
- async authorize(credentials, req) {
- try {
- if (!credentials) throw new Error('No credentials provided');
- const code = await prisma.oAuthToken.findFirstOrThrow({
- where: {
- accessToken: credentials.code,
- },
- });
- const user = await prisma.user.findFirstOrThrow({
- where: {
- id: code.userId,
- },
- });
+ providers: [
+ Credentials({
+ credentials: {
+ code: { label: "code", type: "code" },
+ },
+ async authorize(credentials, req) {
+ try {
+ if (!credentials) throw new Error("No credentials provided");
+ const code = await prisma.oAuthToken.findFirstOrThrow({
+ where: {
+ accessToken: credentials.code,
+ },
+ });
+ const user = await prisma.user.findFirstOrThrow({
+ where: {
+ id: code.userId,
+ },
+ });
- if (!user) return null;
+ if (!user) return null;
- return user;
- } catch (error) {
- return null;
- }
- },
- }),
- ],
- secret: process.env.NEXTAUTH_SECRET,
- session: {
- strategy: 'jwt',
- maxAge: 30 * 24 * 60 * 60,
- },
+ return user;
+ } catch (error) {
+ console.error(error);
+ return null;
+ }
+ },
+ }),
+ ],
+ secret: process.env.NEXTAUTH_SECRET,
+ cookies: {
+ sessionToken: {
+ name: `next-auth.session-token-${process.env.NEXTAUTH_URL}`,
+ options: {
+ httpOnly: true,
+ secure: process.env.NODE_ENV === "production",
+ sameSite: "lax",
+ path: "/",
+ },
+ },
+ },
- adapter: PrismaAdapter(prisma as any),
- callbacks: {
- jwt: async ({ token, user }) => {
- if (user && 'firstname' in user) {
- return {
- ...token,
- ...user,
- };
- }
- return token;
- },
- session: async ({ session, user, token }) => {
- return {
- ...session,
- user: token,
- };
- },
- },
- pages: {
- signIn: '/login',
- signOut: '/logout',
- error: '/authError',
- },
+ session: {
+ strategy: "jwt",
+ maxAge: 30 * 24 * 60 * 60,
+ },
+
+ adapter: PrismaAdapter(prisma as any),
+ callbacks: {
+ jwt: async ({ token, user }) => {
+ if (user && "firstname" in user) {
+ return {
+ ...token,
+ ...user,
+ };
+ }
+ return token;
+ },
+ session: async ({ session, user, token }) => {
+ return {
+ ...session,
+ user: token,
+ };
+ },
+ },
+ pages: {
+ signIn: "/login",
+ signOut: "/logout",
+ error: "/authError",
+ },
} satisfies AuthOptions;
export const getServerSession = async () => getNextAuthServerSession(options);