Closed muratcali closed 6 months ago
hello @muratcali . Sorry to hear you are experiencing issues with the library. We will reproduce this issue and will follow up with any updates
hey @muratcali . I'm not able to reproduce the issue, the sign-in API is working on my end. The sign-in API shouldn't return the User needs to be authenticated
message but instead it would throw a UserAlreadyAuthenticated
exception if it detects cookies stored.
Could you clarify whether the API is returning or throwing an error ?
Hello, @muratcali š. I couldn't reproduce this either when following the docs for using Auth and the signIn()
API for an SSR app. Have another question for you in addition to what @israx asked in the above comment to see if we can unblock you.
Can you share a little more about what you're trying to do on the server side? With you setting ssr
to true
in your call of Amplify.configure(config, { ssr: true })
, you may need to import additional functions such as createKeyValueStorageFromCookieStorageAdapter
, createUserPoolsTokenProvider
, createAWSCredentialsAndIdentityIdProvider
, and unWithAmplifyServerContext
if you're attempting to call any of these Auth API's on the server side. I just didn't see them imported anywhere in the code snippets provided.
Hey, I'm facing a similar issue using aws-amplify "^6.0.12" and nextjs "14.1.0" with app router, in client side everything works as expected, but then hitting my middleware or any backend route with a request shows that the authenticated user is not defined.
So basically I'm able to create an account and sign in from my nextjs app, but if I hit a backend route or the middleware.ts file it seems that I'm not authenticated after all, or the session is not stored correctly. (Doing another sign in returns the error in client side: UserAlreadyAuthenticatedException: There is already a signed in user.
)
Error in middleware/backend routes:
[NotAuthorizedException: Unauthenticated access is not supported for this identity pool.] {
name: 'NotAuthorizedException',
$metadata: {
attempts: 1,
httpStatusCode: 400,
requestId: '5bd172d7-26ff-408b-a5b5-2925a9ebb64b',
extendedRequestId: undefined,
cfId: undefined
}
I followed the updated documentation, this is my middleware.ts file:
import { NextRequest, NextResponse } from "next/server";
import { fetchAuthSession } from "aws-amplify/auth/server";
import { runWithAmplifyServerContext } from "@/providers/amplify-server";
export async function middleware(request: NextRequest) {
const response = NextResponse.next();
const authenticated = await runWithAmplifyServerContext({
nextServerContext: { request, response },
operation: async (contextSpec) => {
try {
const session = await fetchAuthSession(contextSpec);
return !!session.tokens;
} catch (error) {
console.log(error);
return false;
}
},
});
if (authenticated) {
return response;
}
return NextResponse.redirect(new URL("/login", request.url));
}
export const config = {
matcher: "/dashboard/:path*",
};
This is my login function: (being called in a client page with "use client" statement)
import {
signIn,
type SignInInput,
} from "aws-amplify/auth"
async function handleSignIn({ username, password }: SignInInput) {
try {
const response = await signIn({ username, password })
return response
} catch (error: any) {
console.error(error)
toast(error?.message || "Something went wrong, please try again.")
return null
}
}
And this is how I'm calling this handleSignIn function in my login page:
import { handleSignIn } from "@/lib/auth"
...
const onSubmit = async (values: FormType) => {
const response = await handleSignIn(values);
if(!response) return;
router.push('/dashboard'); //doing this is hitting the middleware, but is returning me to the same login page because for the middleware I'm not authenticated.
}
...
And lastly, this is how I'm setting up AWS Amplify in both server and client sides:
// server config
import { cookies } from "next/headers";
import { Amplify } from "aws-amplify"
import { fetchAuthSession } from "aws-amplify/auth";
import { cognitoUserPoolsTokenProvider } from "aws-amplify/auth/cognito"
import { defaultStorage } from "aws-amplify/utils"
import { generateServerClientUsingCookies } from "@aws-amplify/adapter-nextjs/api";
import { createServerRunner } from "@aws-amplify/adapter-nextjs";
import config from "@/aws-exports"
Amplify.configure(config, {
ssr: true,
})
cognitoUserPoolsTokenProvider.setKeyValueStorage(defaultStorage)
export const serverClient = generateServerClientUsingCookies({
config,
cookies,
});
export const { runWithAmplifyServerContext } = createServerRunner({
config,
});
//client config
"use client";
import { Amplify } from "aws-amplify"
import { defaultStorage } from "aws-amplify/utils";
import { cognitoUserPoolsTokenProvider } from "aws-amplify/auth/cognito";
import config from "@/aws-exports"
Amplify.configure(config, {
ssr: true,
})
cognitoUserPoolsTokenProvider.setKeyValueStorage(defaultStorage)
export default function ConfigureAmplifyClientSide() {
return null;
}
If you need more information feel free to ping me.
Hey guys my bad š
. I just find out that this line:
cognitoUserPoolsTokenProvider.setKeyValueStorage(defaultStorage)
Was the cause of the issue for me, I saw it here in the docs so I never thought that line will be causing issues in my app lol. Let me know if that's an expected behavior. But I believe it's not.
Now everything works great!
Thanks for your help and message.
@israx the error im receiving is UserUnAuthenticatedException: User needs to be authenticated to call this API.
@cwomack Here are some code snippets from my serverside code:
Middleware.tsx
import { match } from "@formatjs/intl-localematcher";
import Negotiator from "negotiator";
import { site } from "./configuration";
import { NextRequest, NextResponse } from "next/server";
import { runWithAmplifyServerContext } from "@/utils/amplifyServerUtils";
import { fetchAuthSession } from "aws-amplify/auth/server";
//prettier-ignore
const { languages: { locales } } = site;
//prettier-ignore
const { languages: { defaultLocale } } = site;
function getLocale(request: NextRequest) {
let headers: any = {
"accept-language": request.headers.get("accept-language"),
};
const languages = new Negotiator({ headers }).languages();
return match(languages, locales, defaultLocale);
}
export async function middleware(request: NextRequest) {
const response = NextResponse.next();
const { pathname } = request.nextUrl;
const authenticated = await runWithAmplifyServerContext({
nextServerContext: { request, response },
operation: async (contextSpec) => {
try {
const session = await fetchAuthSession(contextSpec);
console.log(session);
return session.tokens !== undefined;
} catch (error) {
console.log(error);
return false;
}
},
});
const locale = getLocale(request);
const pathnameHasLocale = locales.some(
(locale) =>
pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
);
if (pathname.includes("/portal") && authenticated) {
const dashboardPath = pathnameHasLocale
? `${pathname}/dashboard`
: `/${locale}${pathname}/dashboard`;
if (pathname === `/${locale}/portal`) {
request.nextUrl.pathname = dashboardPath;
return Response.redirect(request.nextUrl);
}
if (pathnameHasLocale) return;
request.nextUrl.pathname = `/${locale}${pathname}`;
return Response.redirect(request.nextUrl);
}
if (pathname.includes("/portal") && !authenticated) {
request.nextUrl.pathname = `/${locale}/`;
return Response.redirect(request.nextUrl);
}
if (!pathname.includes("/portal")) {
if (pathnameHasLocale) return;
request.nextUrl.pathname = `/${locale}${pathname}`;
return Response.redirect(request.nextUrl);
}
}
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};
AmplifyServerUtils.tsx
import { createServerRunner } from "@aws-amplify/adapter-nextjs";
import config from "@/amplifyconfiguration.json";
export const { runWithAmplifyServerContext } = createServerRunner({
config,
});
Thanks in advance.
hello @muratcali . It seems that fetchAuthSession
is being called in the middleware before the user is authenticated. Hence the UserUnAuthenticatedException: User needs to be authenticated to call this API
exception. Can you see the network requests after calling the signIn
API and see if there are any calls to InitiateAuth
and ResponseToAuthChallenge
?
I am experiencing this error as well. In my scenario (which may differ from the OP's), the issue appears to be happening only when I'm using a custom hostname during development; the issue does not occur when using localhost
.
Here is a test repo with repro steps in the readme: https://github.com/ryanwalters/amplify-6
If I were to hazard a guess, Amplify is successfully writing the cookies but to the wrong domain. So when it tries to read those cookies to call getCurrentUser
we're "not authenticated".
Maybe there should be an option to pass an instance of CookieStorage
to libraryOptions
?
Amplify.configure(config, {
ssr: true,
cookieStorage: new CookieStorage({
domain: 'mydomain.com',
...
}),
});
HiĀ @ryanwalters Currently,Ā adapter-nextjs
doesn't provide an interface for configuring theĀ SetCookie
Ā options from the server side. Therefore, if the cookies have been updated from the server side, theĀ domain field will be the default value. We are looking into expanding the interface with supporting other relevant features. In the meantime, if you are looking for fully customizable SetCookie options on the server side, you may also consider using the low-level adapter exported from the aws-amplify/adapter-core
. SeeĀ this documentĀ for details.
Hi @muratcali thanks for providing more details. Could you do the following for verifying a few things:
console.log(isSignedIn, nextStep);
in your handleSignIn
functionThanks.
@muratcali, just wanted to check in and see if you saw @HuiSF's comment and recommendations above. Can you also see if disabling the middleware changes anything to see if we can isolate it to that even further? Thanks
Closing this issue as we have not heard back from you. If you are still experiencing this, please feel free to reply back and provide any information previously requested and we'd be happy to re-open the issue.
Thank you!
I have the same issue, auth tokens are not stored for the ms teams tab. So I get user needs to be authenticated to call this api error.
auth tokens are not stored for the ms teams tab
By "ms teams tab", is this tab under a different domain (other than the domain you have your end users signed in)? @didemkkaslan
Before opening, please confirm:
JavaScript Framework
Next.js
Amplify APIs
Authentication
Amplify Version
v6
Amplify Categories
No response
Backend
Amplify CLI
Environment information
Describe the bug
When I run the signIn command imported from
import { signIn, type SignInInput } from "aws-amplify/auth";
in a file marked withuse client
it returns te following error:User needs to be authenticated to call this API
. Ive also enables SSR inside Amplify.configure. I really can't figure out how to fix this problem for days now. Ive followed every step in the official docs. Thanks in advance.Expected behavior
The command needs to sign me in.
Reproduction steps
Code Snippet
Login.tsx:
useSignIn.ts:
layout.tsx:
amplifyConfigureOnClient.ts:
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