-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NextJS Unknown: an unknown error has occurred. underlyingError: tA [Error]: Cookies can only be modified in a Server Action or Route Handler. #14200
Comments
Hi @Ammar-Raneez thanks for opening this issue. First of all, any particular reason that you are using the generic Regarding the error you encountered: looking at your own implementation of the set(name, value) {
cookies().set(name, value, { path: '/', httpOnly: true, secure: true, sameSite: 'lax' });
}, According to Next.js requirements, you can only call |
Thank you for the response, I tried migrating over to use the nextJS adapter, which is when I get #13966 import { getServerUser } from '@client/services/auth.server.service';
import { DesktopSidebar } from './sidebarItems/desktopSidebar';
const AppSidebar = async () => {
const { email, isAdmin } = await getServerUser(); <--------- Issue
return (
<DesktopSidebar isAdmin={isAdmin} userEmail={email} />
);
};
export default AppSidebar;
const getServerUser = async () => {
try {
const currentUser = await serverRunner.runWithAmplifyServerContext({
nextServerContext: { cookies },
operation: (contextSpec) => getCurrentUser(contextSpec),
});
return { email: currentUser.signInDetails?.loginId, isAdmin: true };
} catch (error) {
console.error(error);
return { email: undefined, groups: undefined, isAdmin: false };
}
}; The appSidebar is present in RootLayout. When I refresh the page it seems to be working, on login completion this is what happens: const navigateUser = async () => {
const { isAdmin } = await getSession();
if (isAdmin) {
router.push(ROUTES.ADMIN_ACCOUNT_MANAGEMENT);
}
router.push(ROUTES.ACCOUNT);
};
const getSession = async () => {
const currentSession = await fetchAuthSession(); <----------- Imported from amplify/auth
const tokens = currentSession.tokens;
const isAdmin = tokens?.accessToken.payload['cognito:groups']?.toString()?.includes('Admins');
return { currentSession, isAdmin };
}; |
Hi @Ammar-Raneez thanks for following up. Re:
Could you provide details about how are you implementing the sign-in? In general, since the sign-in is performed on the client side - exchanging auth tokens and writing them into cookie store are also done on the client side. So after signing in, and before the auth token cookies are written into the cookie store, if you access a route that invokes server-side To mitigate this, you can use client-side |
Hi, yea sure: Sign in is simply a client side call to amplify/auth signIn: const signin = async (username: string, password: string): Promise<SignInOutput> => {
return signIn({
username,
password,
});
}; The above is called in a LoginForm component as follows: const onLogin = async (values: LoginFormFields) => {
const res = await signin(values.email, values.password);
} Since the appSidebar is called from the RootLayout (which gets triggered even when in the login page): import { getServerUser } from '@client/services/auth.server.service';
import { DesktopSidebar } from './sidebarItems/desktopSidebar';
const AppSidebar = async () => {
const { email, isAdmin } = await getServerUser();
return (
<DesktopSidebar isAdmin={isAdmin} userEmail={email} />
);
};
export default AppSidebar; Do you suggest using client side get user and session converting the into a client component? Or another way I could could about this is by having two separate layouts? |
Hi @Ammar-Raneez since your
In addition, you can refresh the page after calling the client-side const router = useRouter();
const onSignIn = async () => {
const result = await signIn({ username: 'username', password: 'password' });
if (result.isSignedIn) {
router.reload();
// or your can redirect to a new route e.g. `/home` which will send token cookies to your server
}
} |
I went ahead with the refreshing approach and handling the error of the sidebar - seems to be working fine for now ❤️ Thank you for your time! |
Before opening, please confirm:
JavaScript Framework
Next.js
Amplify APIs
Authentication
Amplify Version
v6
Amplify Categories
auth
Backend
CDK
Environment information
Describe the bug
I'm trying to connect Amplify auth with my NextJS app and have run into multiple issues.
Using Amplify v6, I initially tested out via Gen 2, and ran into this same issue that is currently open: #13966
The issue I'm facing right now is that authentication works, but the server user returns undefined, due to the below error.
I end up getting the following error
I understand it seems to be a cookie modification issue as mentioned in the underlyingError; however, I haven't been able to diagnose this yet.
The user is authenticated, as a client login returns
UserAlreadyAuthenticatedException: There is already a signed in user.
Help would be very much appreciated!!
Expected behavior
Simple expectation: the cookie flow must work as expected in the client and server side. Client side seems to be flawless, but it's the server side giving the headache.
Reproduction steps
Code Snippet
Lastly, the client and server providers:
Log output
aws-exports.js
No response
Manual configuration
No response
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
No response
The text was updated successfully, but these errors were encountered: