Next.js Discord

Discord Forum

How do you use the data from `useSession` in getServerSideProps?

Unanswered
Transvaal lion posted this in #help-forum
Open in Discord
Avatar
Transvaal lionOP
I need to extract some data from useSession and use it as a header for a fetch in getServerSideProps

fetch(url, {
        headers: {
            "Authorization": `Bearer ${data?.accessToken}`
        }
    }).then(async r => await r.json()).then(async r => {
        // console.log("Fetched")
        return await r
    })

but data is
 const { data } = useSession()

and I cannot use hooks in getServerSideProps, so how would I extract the information that I need from useSession and use it in getServerSideProps?

41 Replies

Avatar
Northern Wheatear
What data do you actually need from useSession
Avatar
Transvaal lionOP
I need the access token to be used in the headers.
Avatar
risky
Avatar
Transvaal lionOP
I have tried this suggestion, but the session variable keeps coming back as undefined
export const getServerSideProps: GetServerSideProps = async (context) => {

    const url = `https://us.api.blizzard.com/profile/user/wow?namespace=profile-us&locale=en_US`



    const session = await getServerSession(context.req, context.res, authConfig())


    if (!session)
        return {
            redirect: {
                destination: "/",
                permanent: false
            }
        }

    return {
        props: {
            session
        }
    }
}


I'll post the [...nextauth].ts if needed.

ERROR
[Error]: Error serializing .session.user.email returned from getServerSideProps in "/WoW".

Reason: undefined cannot be serialized as JSON. Please use null or omit this value.
Avatar
risky
The error is when you are returning session and not just getting
Avatar
Transvaal lionOP
Well, then what's the solution for this?
Avatar
risky
Look at the object (via console.log) and see what you need, then just return that subset and if a value is undefined then make it null
Avatar
Transvaal lionOP
The entire session object is undefined.
Whenever I use the fetch inside the component however, it seems to work just fine. This only happens when the fetch is done inside the getServerSideProps function.
Avatar
risky
hmm... why is authOptions being ran and not just passed in like docs show?
Avatar
Transvaal lionOP
I use it as a function in [...nextauth].ts, but I have also used the authOptions (or authConfig as how I have it in mine) and it still didn't work.
Avatar
risky
i was meaning if it works like authConfig instead of authConfig(), but i may have missunderstood your setup
Avatar
Transvaal lionOP
I'm not really sure why it doesn't work. I got an unauthorized response from axios and no data, but it makes no sense to get this, because it works just fine if I use it in the component and not the getServerSideProps.
Avatar
risky
sorry that i can't help as i haven't used next auth in getprops... (and i haven't really used pages dir either much)
Avatar
Transvaal lionOP
All good! Hopefully someone else knows what to do
Avatar
Alfonsus Ardani
use getServerSession?
Avatar
risky
isn't this using getServerSession?
Avatar
Alfonsus Ardani
may we see the authConfig()?
Avatar
Transvaal lionOP
import { DefaultSession, NextAuthOptions, User, getServerSession } from "next-auth";
import BattleNetProvider from "next-auth/providers/battlenet"
import GithubProvider from "next-auth/providers/github"
import NextAuth from "next-auth/next";
import type { NextApiRequest, NextApiResponse } from "next";

declare module 'next-auth' {
    /**
     * Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
     */
    interface Session { 
      accessToken?: string
    }
  }

export const authConfig = ():NextAuthOptions => {
    return ({

    providers: [
        BattleNetProvider({
            clientId: process.env.BNET_CLIENT_ID as string,
            clientSecret: process.env.BNET_CLIENT_SECRET as string,
            issuer: "https://us.battle.net/oauth",
            
            authorization: {
                
                params:{
                    client_id: process.env.BNET_CLIENT_ID ,
                    scope:"openid wow.profile sc2.profile d3.profile",  
                    redirect_uri: process.env.BNET_REDIRECT_URL, 
                    response_type:"code"}
            }

        }), 
        
   
    ],
    callbacks: {
    async jwt({ token, account }) {
        // Persist the OAuth access_token to the token right after signin
        if (account) {
        token.accessToken = account.access_token
        }
        return token
    },
    async session({ session, token, user } )  {

        session.accessToken = token.accessToken as string
        return session
    },
    async redirect({baseUrl}) {

        return baseUrl
    }
    },


    })

}


export default async function auth(req : NextApiRequest, res:NextApiResponse){

    return await NextAuth(req,res,authConfig())
}
Avatar
Alfonsus Ardani
does authConfig accept any parameter?
Avatar
Transvaal lionOP
No parameters.
Avatar
Alfonsus Ardani
hmmmmmmmmmmmmmmmmmmmmm
Avatar
Transvaal lionOP
I'm also very confused.
Avatar
Alfonsus Ardani
whats the point of making it an arrow function if it doesn't accept any parameters
but i digress
Avatar
Transvaal lionOP
Eventually, I will want to customize the auth in the function, so I have it as a template for the moment.
Avatar
Alfonsus Ardani
aight
if it doesnt show session that means its not logged in? have you tried logging it?
is the user logged in?
Avatar
Transvaal lionOP
Of course. The user is definitely authenticated. I log it in the component without getServerSideProps and it works fine. Although, I do receive a few undefined values a few times in the console, it later displays the information. I'm just confused on why this works without the getServerSideProps. I was hoping to run this on build time.
Avatar
Alfonsus Ardani
how do you log it in the component without getServerSideProps?
Avatar
Transvaal lionOP
As in
const WoW = () => {

const [select, setSelect] = useState("")
    const { data } = useSession()

 const url = `https://us.api.blizzard.com/profile/user/wow?namespace=profile-us&locale=en_US`

    const getWoWdata = fetch(url, {
        headers: {
            "Authorization": `Bearer ${data?.accessToken}`
        }
    }).then(async r => await r.json()).then(async r => {
        // console.log("Fetched")
        return await r
    })
  console.log(getWoWdata)
//....
Avatar
Alfonsus Ardani
hmmmmmmmmmmmmmm
Avatar
Northern Wheatear
@Transvaal lion U could try to get the token from cookies right? Its name should be next-auth.session-token
And then decode the cookie to get data
Avatar
Transvaal lionOP
But I shouldn't be putting it in any cookies to begin with when I can just use it when it's in the session already. The token only appears when I don't run the fetch during build time. I feel like I'm missing something.
Avatar
Northern Wheatear
No you dont need to put any cookies... I think I wasn't clear to you
I will paste an example
Avatar
Northern Wheatear
import { decode } from 'next-auth/jwt'

export async function getServerSideProps(context) {
    const jwt = context.req.cookies['next-auth.session-token']
    const decodedToken = await decode({ token: jwt, secret: process.env.NEXTAUTH_SECRET, })
}
This decodedToken will contain the same data useSession provides... I'm not 100% sure but decodedToken will contain definitely the user data
Pls let me know if this works @Transvaal lion