amplify-js: Auth.currentAuthenticatedUser does not work in NextJs API routes
Before opening, please confirm:
- I have searched for duplicate or closed issues and discussions.
- I have read the guide for submitting bug reports.
- I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
React, Next.js
Amplify APIs
Authentication
Amplify Categories
auth
Environment information
@aws-amplify/api: ^5.0.7 => 5.0.7
@aws-amplify/auth: ^5.1.1 => 5.1.1
@aws-amplify/core: ^5.0.7 => 5.0.7
@aws-amplify/storage: ^5.0.7 => 5.0.7
Describe the bug
The authenticated user is not returned in an API route, even though it is returned on client side and getServerSideProps
Expected behavior
When used as
export async function getServerSideProps(context) {
const { API, Auth } = withSSRContext(context);
on a nextJs page, this works as expected. However, in API routes, it seems to return an error.
Reproduction steps
Set up a route in API/anyRoute.
Hit the API from nextJs client side.
See that the authenticated user is not returned.
Code Snippet
import { buffer } from "micro";
import Cors from "micro-cors";
import { NextApiRequest, NextApiResponse } from "next";
import { withSSRContext } from "aws-amplify";
import Amplify from "@aws-amplify/core";
import aws_exports from "@/aws_exports";
import Stripe from "stripe";
import { oauth, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET } from "@/deploy_constants";
const stripe = new Stripe(STRIPE_SECRET_KEY, {
// https://github.com/stripe/stripe-node#configuration
apiVersion: "2020-08-27",
});
const webhookSecret: string = STRIPE_WEBHOOK_SECRET;
// Amplify SSR configuration needs to be enabled within each API route
Amplify.configure({
...aws_exports,
oauth: {
...oauth,
},
ssr: true,
});
// Stripe requires the raw body to construct the event.
export const config = {
api: {
bodyParser: false,
},
};
const cors = Cors({
allowMethods: ["POST", "HEAD"],
});
const webhookHandler = async (req: NextApiRequest, res: NextApiResponse) => {
console.log("REQ", req.cookies);
const { Auth } = withSSRContext({ req });
try {
const user = await Auth.currentAuthenticatedUser();
console.log("GOT", user);
} catch (e) {
console.log("ERERER", e);
}
if (req.method === "POST") {
const buf = await buffer(req);
const sig = req.headers["stripe-signature"]!;
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(buf.toString(), sig, webhookSecret);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : "Unknown error";
// On error, log and return the error message.
if (err! instanceof Error) console.log(err);
console.log(`❌ Error message: ${errorMessage}`);
res.status(400).send(`Webhook Error: ${errorMessage}`);
return;
}
// Successfully constructed event.
console.log("✅ Success:", event.id);
// Cast event data to Stripe object.
if (event.type === "invoice.payment_failed") {
// TODO: grant user access until checkoutSession.expires_at
const invoice = event.data.object as Stripe.Invoice;
console.log(`❌ Payment failed: ${invoice.subscription}`);
} else if (event.type === "invoice.paid") {
// TODO: grant user access until invoice.period_end
const invoice = event.data.object as Stripe.Invoice;
console.log(
`💵 Paid successfully. ${invoice.subscription}: FROM ${invoice.period_start} TO ${invoice.period_end}`
);
} else {
console.warn(`🤷♀️ Unhandled event type: ${event.type}`);
}
// Return a response to acknowledge receipt of the event.
res.json({ received: true });
} else {
res.setHeader("Allow", "POST");
res.status(405).end("Method Not Allowed");
}
};
export default cors(webhookHandler as any);
Log output
REQ {}
ERERER The user is not authenticated
Seems like req.cookies are not set.
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
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 26 (12 by maintainers)
bumping again as it is happening again for me.
On client side, all Auth calls work as expected, but from SSR,
SSR.Auth.currentAuthenticatedUserthrows the errorThe user is not authenticatedThe developer preview for v6 of Amplify has officially been released with improvements to SSR support and much more! Please check out our announcement and updated documentation to see what has changed.
This issue should be resolved within the dev preview and upcoming General Availability for Amplify v6, but let us know with a comment if there are further issues.
still occurring. next-js app router middleware. cannot use even with SSR enabled in Amplify config
I’m also seeing this in a Nextjs API route. I’ve configured Amplify with:
but I’m still seeing unauthenticated credentials:
I had the same issue. After hours of debugging, we found that we have two places of code where
Auth.configurewas called differently.In one route (with usage of
getServerSideProps):In another (where we used only client side):
After adding
ssr: trueinto the second case, it resolved the problem. The issue was not reproducible on local dev env with next.js. Only the production version had this issue. I assume it is somehow related to page preloading in nextjs.I’m getting this also when using server side components with the new app router that is about to be released.
Here’s the code I’m using
and the logs when it fails.
I am having the same problem as well.
The authentication works fine on the client-side, but as soon as any page is redirected after a successful authentication and the SSR enters in action, the user is undefined.
dependency:
_app.js
internal page:
Same issue
@nadetastic Also one more thing, calling API.graphql (from SSR) from seems to also return an Error: No current user, even though
both console logs work properly, but calling the API throws the errors