You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Please help me! I try now since two days to solve that issue.
I try to use the unstable_getServerSession in an nextJS API route (before I was using a custom authentication method)
Maybe I have a wrong setup with JWT? Maybe I can't see the forest for the trees anymore
in the getServerSideProps function I call my next/API endopoint via a Axios
I pass Bearer token to the next/API call
the API endpoint should authorize that user is allowed to call it by JWT
the API endpoint then should fetch Stripe subscriptions based on the stripe_customer_id embedded in the JWT
But whatever I try the session and token in the next/API endpoint is always null
This is my getServerSideProps function:
exportconstgetServerSideProps: GetServerSideProps=async(context: GetServerSidePropsContext)=>{// ### contains the correct SESSION (it works!)constsession=awaitunstable_getServerSession(context.req,context.res,authOptions)// ### contains the correct TOKEN (it works!)consttoken=awaitgetToken(context).then(token=>{returntoken.tokenasstring;})if(!session){return{redirect: {permanent: false,destination: url.accountSignIn().href,},};}else{// My SESSION IS AVAILABLE (I use this to show user data.// #### NOW I CALL THE NEXT/API endpoint with the getToken() responseconststripeSubscriptions=awaitaxios.get(`${process.env.NEXT_PUBLIC_URL}/api/account/subscriptions`,{headers: {'Authorization': 'Bearer '+token}}).then(res=>{console.log('res.data :>> ',res.data);constsubscriptions=res.data.dataasStripe.Subscription[]returnsubscriptions}).catch((err: any)=>{console.log("Dashboard ERR",err.response.data.message||err);// #### I ALWAYS END with {
error: "Unauthorized",message: "not authorized",data: []}signOut({callbackUrl: 'http://localhost:8000/account/login'})returnerr.response.data});return{props: { stripeSubscriptions, session },// will be passed to the page component as props};}
This is my next/API/endpoint /api/account/subscriptions
import{NextApiRequest,NextApiResponse}from'next';importStripefrom'stripe';constsecret=process.env.NEXTAUTH_SECRET// #### is correctimport{unstable_getServerSession}from"next-auth/next"import{authOptions}from"../../api/auth/[...nextauth]"import{getToken}from"next-auth/jwt"exportdefaultasync(req: NextApiRequest,res: NextApiResponse)=>{// #### the header definitely has the Bearer token in it's request: req.headers.authorization: `"Bearer eyJhbGciOiJIUzI1NiJ9......"`constsession=awaitunstable_getServerSession(req,res,authOptions)// ### ALWAYS RETURNS "NULL"consttoken=awaitgetToken({ req, secret })// ### ALWAYS RETURNS "NULL"if(session){// ### ALWAYS "NULL"returnnewPromise<void>((resolve)=>{constcustomer_id=session.stripe_idasstring;// #### should get extracted from JWTconststripe=newStripe(process.env.STRIPE_API_SECRET!,{apiVersion: '2020-08-27'});stripe.subscriptions.list({customer: customer_id}).then(subscriptions=>{res.status(200).json({data: subscriptions});returnresolve();}).catch(err=>{res.status(500).json({error: `Stripe Subscriptions error: ${err.message}`});returnresolve();});})}else{// Not Signed in// #### I ALWAYS END HEREres.status(401).json({error: 'Unauthorized',message: "not authorized",data: []});}res.end()
and here is my COMPLETE [...nextauth].ts file:
I have to mention, that a Rails backend creates the JWT.
importjwtDecodefrom'jwt-decode';importNextAuthfrom'next-auth';importtype{NextAuthOptions}from'next-auth';importProviderCredentialsfrom'next-auth/providers/credentials';import{JWT}from'next-auth/jwt';exportconstauthOptions: NextAuthOptions={// Configure one or more authentication providersproviders: [ProviderCredentials({id: 'credentials',name: 'credentials',credentials: {username: {label: 'Email',type: 'email',placeholder: '[email protected]',},password: {label: 'Passwort',type: 'password'},},asyncauthorize(credentials,req){// The 'url' is pointing to a Rails API endpoint which returns a JWT Token, and account dataconsturl=`${process.env.NEXT_PUBLIC_API_URL}/auth/login`;constres=awaitfetch(url,{method: 'POST',body: JSON.stringify(credentials),headers: {'Content-Type': 'application/json',},});constuser=awaitres.json();// If no error and we have user data, return itconsole.log('user authorize :>> ',user);if(user&&(user.error||user.message)){thrownewError(user.message||user.error);}if(res.ok&&user){returnuser;// MY CONTENT}// Return null if user data could not be retrievedreturnnull;},}),],session: {strategy: 'jwt',},// callback is where we decide whether the token is ready to be refreshed.jwt: {secret: process.env.NEXTAUTH_SECRET,},secret: process.env.NEXTAUTH_SECRET,callbacks: {// This callback is called whenever a JSON Web Token is created (i.e. at sign in)// or updated (i.e whenever a session is accessed in the client).// The returned value will be signed and optionally encrypted,// and it is stored in a cookie// The arguments user, account, profile and isNewUser are only passed the first time// this callback is called on a new session, after the user signs in.// In subsequent calls, only token will be available.asyncjwt(props){var{ token, user, account, profile, isNewUser }=propsconsole.log('JWT: props :>> ',props);// This user return by provider {} as you mentioned above MY CONTENT {token:}if(user){if(user.token){vartoken={token: user.token,name: user.name,email: user.email,shop: user.shop,stripeId: user.stripe_id,billingAddress: user.billingAddress,};}}returntoken;},// controls if a user is allowed to sign in.// user object is the response returned from the authorize callbackasyncsignIn(props){const{ user, account }=propsconsole.log('signIn: props :>> ',props);returntrue;},// signs out the user// user object is the response returned from the authorize callbackasyncsignOut({ token, session }){console.log('signOUT token :>> ',token);console.log('signOUT session :>> ',session);returntrue;},// session callback is where we specify what will be available on the client with useSession() or getSession().// The session callback is called WHENEVER a SESSION IS CHECKED.// By default, only a subset of the TOKEN is returned for increased security.// If you want to make something available you ADDED TO THE TOKEN through the jwt() callback,// you have to explicitly forward it here to make it available to the client.asyncsession(props){const{ session, token, user }=props;console.log('session: props :>> ',props);// first time jwt callback is run, user object is availableif(token){session.user=token;}//if you want to add user details inforeturnsession;},redirect({ url, baseUrl }){if(url.startsWith(baseUrl))returnurl;// Allows relative callback URLselseif(url.startsWith('/'))returnnewURL(url,baseUrl).toString();returnbaseUrl;},},pages: {signIn: 'account/login',// signOut: 'account/logout',// error: '/auth/error', // Error code `passed` in query string as ?error=// verifyRequest: '/auth/verify-request', // (used for check email message)// newUser: '/auth/new-user', // New users will be directed here on first sign in (leave the property out if not of interest)},// events: {// async signIn(message) {// console.log('user sign in EVENT called ;:>> ', message);// },// async signOut(message) {// console.log('user sign out EVENT called ;:>> ', message);// },// },};exportdefaultNextAuth(authOptions);
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Please help me! I try now since two days to solve that issue.
I try to use the
unstable_getServerSession
in an nextJS API route (before I was using a custom authentication method)Maybe I have a wrong setup with JWT? Maybe I can't see the forest for the trees anymore
I followed the tutorial "Securing API routes":
pages/api/get-session-example.js
https://next-auth.js.org/tutorials/securing-pages-and-api-routes#securing-api-routes
getServerSideProps
function I call my next/API endopoint via a AxiosBearer token
to the next/API callstripe_customer_id
embedded in the JWTBut whatever I try the
session
andtoken
in the next/API endpoint is alwaysnull
This is my
getServerSideProps
function:This is my next/API/endpoint
/api/account/subscriptions
and here is my COMPLETE
[...nextauth].ts
file:I have to mention, that a Rails backend creates the JWT.
Please help me, What I am doing wrong?
Beta Was this translation helpful? Give feedback.
All reactions