使用 NextAuth 通过凭据进行身份验证时,为什么地址栏在成功后不会自动更新为正确的路径?

问题描述 投票:0回答:1

如何在成功的凭据登录后自动刷新 url 路径?

我试图创建类似于 Next 在他们的教程此处中列出的凭据身份验证。不过我只使用电子邮件作为身份验证。

我能够成功登录,但地址栏中的路径没有更新。它应该从

/login
/dashboard
。仅在手动刷新页面后更新。如果没有更新,我将无法在单击“退出”后退出。仅当我手动刷新页面且地址发生更改时,我才能注销。您可以在下面的 gif 中看到这一点。

我的文件夹结构如下所示。

enter image description here

// ./auth.config.ts

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

export const authConfig = {
  pages: {
    signIn: '/login',
  },
  callbacks: {
    authorized({ auth, request: { nextUrl } }) {
      const isLoggedIn = !!auth?.user;
      const isOnDashboard = nextUrl.pathname.startsWith('/dashboard');
      if (isOnDashboard) {
        if (isLoggedIn) return true;
        return false; // Redirect unauthenticated users to login page
      } else if (isLoggedIn) {
        return Response.redirect(new URL('/dashboard', nextUrl));
      }
      return true;
    },
  },
  providers: [],
} satisfies NextAuthConfig;
// ./middleware.ts

import NextAuth from 'next-auth';
import { authConfig } from './auth.config';

export default NextAuth(authConfig).auth;

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
};
// ./auth.ts

import NextAuth from 'next-auth';
import Credentials from 'next-auth/providers/credentials';
import { z } from 'zod';
import { sql } from '@vercel/postgres';
import { authConfig } from './auth.config';
import type { User } from '~/lib/definitions';

async function getUser(email: string): Promise<User | undefined> {
  try {
    const user = await sql<User>`SELECT * FROM users WHERE email=${email}`;
    return user.rows[0];
  } catch (error) {
    console.error('Failed to fetch user:', error);
    throw new Error('Failed to fetch user.');
  }
}

export const { auth, signIn, signOut } = NextAuth({
  ...authConfig,
  providers: [
    Credentials({
      async authorize(credentials) {
        const parsedCredentials = z
          .object({ email: z.string().email() })
          .safeParse(credentials);

        if (parsedCredentials.success) {
          const { email } = parsedCredentials.data;
          const user = await getUser(email);
          if (user) return user;
          return null;
        }
        return null;
      },
    }),
  ],
});

// ./app/lib/actions.ts

'use server';

import { AuthError } from 'next-auth';
import { signIn } from '~/../auth';

export async function authenticate(
  prevState: string | undefined,
  formData: FormData
) {
  try {
    await signIn('credentials', formData);
  } catch (error) {
    if (error instanceof AuthError) {
      switch (error.type) {
        case 'CredentialsSignin':
          return 'Invalid credentials.';
        default:
          return 'Something went wrong.';
      }
    }
    throw error;
  }
}
// ./app/login/page.tsx

'use client';

import { useFormState, useFormStatus } from 'react-dom';
import { authenticate } from '~/lib/actions';

export default function LoginPage() {
  const [errorMessage, dispatch] = useFormState(authenticate, undefined);

  return (
    <main>
      <form action={dispatch}>
        <div>
          <label htmlFor="email">
            Email
          </label>
          <div>
            <input
              id="email"
              type="email"
              name="email"
              placeholder="Enter your email address"
              required
            />
          </div>
        </div>
        <LoginButton />
      </form>
    </main>
  );
}

function LoginButton() {
  const { pending } = useFormStatus();

  return (
    <button aria-disabled={pending}>
      Sign in
    </button>
  );
}
// ./app/dashboard/page.tsx

import { signOut } from '~/../auth';

export default function Page() {
  return (
    <main>
      <h1>Dashboard</h1>
      <p>Dashboard content goes here</p>
      <form
        action={async () => {
          'use server';
          await signOut({ redirectTo: '/login' });
        }}
      >
        <button>
          <div>Sign Out</div>
        </button>
      </form>
    </main>
  );
}

enter image description here

javascript next.js next-auth
1个回答
0
投票

经过不眠之夜和更多的灰色之后,我找到并适合我的解决方案是通过添加重定向路径来更新 formData。

// ./app/lib/actions.ts

'use server';

import { AuthError } from 'next-auth';
import { signIn } from '~/../auth';

export async function authenticate(
  prevState: string | undefined,
  formData: FormData
) {
  formData.set('redirectTo', '/dashboard'); // <-- this solved the issue
  try {
    await signIn('credentials', formData);
  } catch (error) {
    if (error instanceof AuthError) {
      switch (error.type) {
        case 'CredentialsSignin':
          return 'Invalid credentials.';
        default:
          return 'Something went wrong.';
      }
    }
    throw error;
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.