next-auth icon indicating copy to clipboard operation
next-auth copied to clipboard

Callback URL inside Docker container doesn't work

Open DavDeDev opened this issue 1 year ago • 3 comments

Environment

  System:
    OS: Linux 5.15 Alpine Linux
    CPU: (20) x64 12th Gen Intel(R) Core(TM) i7-12700H
    Memory: 4.38 GB / 7.60 GB
    Container: Yes
    Shell: 1.36.1 - /bin/ash
  Binaries:
    Node: 18.20.1 - /usr/local/bin/node
    Yarn: 1.22.22 - /usr/local/bin/yarn
    npm: 10.5.0 - /usr/local/bin/npm
    pnpm: 8.15.6 - /usr/local/bin/pnpm
  npmPackages:
    @auth/core: ^0.28.2 => 0.28.2 
    @auth/prisma-adapter: ^1.5.2 => 1.5.2 
    next: 14.1.4 => 14.1.4 
    next-auth: 5.0.0-beta.15 => 5.0.0-beta.15 
    react: ^18.2.0 => 18.2.0 

Reproduction URL

https://github.com/CC-Comp308001-Group04/pulsecare-web/pull/11

Describe the issue

I have set a dummy redirectTo: /about in my signIn but when I trigger the action it loops back onto the login page with this URL: http://localhost:3000/auth/login?callbackUrl=http%3A%2F%2Flocalhost%3A3000%2Fabout.

I am using the following cofiguration:

  • Dockerfile
FROM node:18-alpine as base
ENV NEXT_TELEMETRY_DISABLED 1
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
ENV NEXT_TELEMETRY_DISABLED 1
# enbable corepack to use pnpm
RUN corepack enable
COPY . /pulsecare-webapp
WORKDIR /pulsecare-webapp

FROM base AS deps
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
# Trying to freshly install prisma client every time as suggested here: https://github.com/prisma/prisma/issues/7234#issuecomment-846606919
RUN pnpm dlx prisma generate --schema=prisma/schema.prisma


FROM deps as development
ENV HOSTNAME "0.0.0.0"
ENV PORT 3000
CMD ["pnpm", "dev"]
  • docker-compose.yaml:

version: "3.1"
services:
  mongo6:
    profiles:
      - dev
    build:
      context: ./mongodb_rs
      args:
        MONGO_VERSION: 6
    environment:
      # https://github.com/prisma/prisma/issues/11925
      MONGO_REPLICA_HOST: 127.0.0.1
      MONGO_REPLICA_PORT: 27018
      # Use "mongo" instead of "mongosh" before v5.0
      MONGO_COMMAND: "mongosh"
    ports:
      - "27018:27018"
    restart: always
    # networks:
    #   - pulsecare-net

  web_prod:
    profiles:
      - prod
    restart: always
    build:
      context: ..
      dockerfile: docker/Dockerfile
      target: production
    ports:
      - "3000:3000"
  web_dev:
    profiles:
      - dev
    restart: always
    environment:
      # README: https://github.com/prisma/prisma/discussions/23790#discussioncomment-9060992
      - DATABASE_URL=mongodb://mongo6:27018/pulsecare-web?replicaSet=rs0&retryWrites=true&w=majority&directConnection=true
      # For WSL: https://www.reddit.com/r/nextjs/comments/1638ec6/comment/jy1h8ys/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button
      - WATCHPACK_POLLING=true
    build:
      context: ..
      dockerfile: docker/Dockerfile
      target: development
    ports:
      - "3000:3000"
    depends_on:
      - mongo6
    links:
      - mongo6
    # networks:
    #   - pulsecare-net
    # This is only for hot reload in development
    volumes:
      - ../:/pulsecare-webapp
      - /pulsecare-webapp/node_modules
      - /pulsecare-webapp/.next

How to reproduce

  • action that calls the authentication
"use server";

import { db } from "@/lib/prisma-client";
import { DEFAULT_LOGIN_REDIRECT } from "@/lib/routes";
import { LoginSchema } from "@/schemas/login.schema";
import { signIn } from "@/auth";
import { z } from "zod";
import { AuthError } from "next-auth";

interface ErrorOutput {
  error: { type: string; message: string };
}

interface SuccessOutput {
  res: { type: string; message: string };
}
export const login = async (
  values: z.infer<typeof LoginSchema>,
): Promise<ErrorOutput | SuccessOutput> => {
  const validateFields = LoginSchema.safeParse(values);
  if (!validateFields.success) {
    return { error: { type: "403", message: "Invalid fields" } };
  }

  const { email, password } = validateFields.data;
  const existingUser = await db.user.findUnique({ where: { email } });

  if (!existingUser) {
    return { error: { type: "403", message: "Invalid Credentials" } };
  }
  // TODO: hash password
  const passwordMatch: boolean = existingUser.password === password;
  if (!passwordMatch) {
    return { error: { type: "403", message: "Invalid Credentials" } };
  }
  console.log(DEFAULT_LOGIN_REDIRECT);


  try {
    // TODO: implement passinf redirecting URL from client
    await signIn("credentials", {
      email,
      password,

      redirectTo: DEFAULT_LOGIN_REDIRECT,
    });
    // await signIn("passkey")
    return { res: { type: "200", message: "Success" } };
  } catch (error) {
    if (error instanceof AuthError) {
      switch (error.type) {
        case "CredentialsSignin":
          return { error: { type: "403", message: "Invalid credentials" } };
        default:
          return { error: { type: "500", message: "Something went wrong!" } };
      }
    }
    throw error;
  }
};
  • auth.ts:
import NextAuth from "next-auth";
import authConfig from "./auth.config";

import { PrismaAdapter } from "@auth/prisma-adapter";
import db from "./lib/prisma-client";

export const {
  handlers: { GET, POST },
  auth,
  signIn,
  signOut,
} = NextAuth({
  pages: {
    signIn: "/auth/login",
    error: "/auth/error",
  },
  callbacks: {
    async signIn({ user, account }) {   
      console.log("signin auth callback...")
      redirect
      if (account?.provider !== "credentials") return true;
      // await connectToDB();

      // const existingUser = await User.findOne({ email: user.email });
      // // // Allow OAuth without email verification

      return true;
    },
    async session({ session, token, user }) {
      // await connectToDB();

      // if (token.sub && session.user) {
      //   session.user.id = token.sub;
      // }

      // if (token.role && session.user) {
      //   session.user.role = token.role
      // }
      // // Send properties to the client, like an access_token and user id from a provider.

      return session;
    },
    // README: we decided to use JWT as strategy, hence we need to define it
    async jwt({ token, account, profile }) {
      // await connectToDB();
      // if (!token.sub) return token;
      // const existingUser = await User.findById(token.sub)
      // if (!existingUser) return token;

      // token.role = existingUser.role

      return token;
    },
  },
  adapter: PrismaAdapter(db),
  session: { strategy: "jwt" },
  ...authConfig,
});
  • auth.config.ts:
import Google from "@auth/core/providers/google";

import type { NextAuthConfig } from "next-auth";

export default {
  providers: [Google],
} satisfies NextAuthConfig;

Expected behavior

I would like to be redirected to /about

DavDeDev avatar Apr 09 '24 18:04 DavDeDev

any update ??

Edit by maintainer bot: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

teamsmiley avatar Apr 17 '24 14:04 teamsmiley

You must ensure the following environment variables in Docker:

AUTH_SECRET="<secret>"
AUTH_TRUST_HOST="true"
AUTH_URL="http://localhost:3000"

thevuong avatar Jun 03 '24 04:06 thevuong

Same issue

Edit by maintainer bot: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

kewldan avatar Jun 21 '24 16:06 kewldan