-1

I am working on a jwt authentication system in next js 13 with redux toolkit. I have a Django backend and it is communicating with my next js frontend. The problem is in the communication between API page in next js and the redux toolkit to set the user to be logged in. Here is my code in the api page:

export async function POST(request) {
    const body = await request.json();
    const { email, password } = body;
    const bodystring = JSON.stringify({
        email,
        password
    });
    console.log(`Posted data is: ${bodystring}`);
    try {
        const apiRes = await fetch(`${API_URL}/api/token/`, {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
            },
            body: bodystring
        });
        const data = await apiRes.json();
        // console.log(`Data is ${data}`)
        if (apiRes.status === 200) {
            console.log("Login Succesful")
            NextResponse.setHeader('Set-Cookie', [
                cookie.serialize(
                    'access', data.access, {
                        httpOnly: true,
                        secure: false,
                        maxAge: 60 * 30,
                        sameSite: 'strict',
                        path: '/api/'
                    }
                ),
                console.log("Access token set succesfully"),
                cookie.serialize(
                    'refresh', data.refresh, {
                        httpOnly: true,
                        secure: false,
                        maxAge: 60 * 60 * 24,
                        sameSite: 'strict',
                        path: '/api/'
                    }
                ),
                console.log("Refresh token sorted too"),
            ]);
            
            return NextResponse.json({
                // res: body
                success: 'Logged in successfully',
                status: 200,
            });
        }
} catch (error) {
        
    }
}

And then here is my auth.js that is supposed to dispatch the states when user succesfully logs in:

export const login = (email, password) => async dispatch => {
    const body = JSON.stringify({
        email,
        password
    });
    // alert(`body is ${body}`) //This alert is showing data hence it`s working
    dispatch({
        type: SET_AUTH_LOADING
    });
    try {
        const res = await fetch('/auth/login/api', {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: body
        });
        alert(`Response is ${res}`) //There is a problem here. Check the page api
        if (res.status === 200) {
            alert("Login Succesful")
            dispatch({
                type: LOGIN_SUCCESS
            });
            dispatch(load_user());
        } else {
            alert("Login Failed")
            dispatch({
                type: LOGIN_FAIL
            });
        }
    } catch (error) {
        dispatch({
            type: LOGIN_FAIL
        });
    }

    dispatch({
        type: REMOVE_AUTH_LOADING
    });
}

When the program runs, the auth.js sends an alert Response is [object Response] and then I get the error error TypeError: Cannot read properties of undefined (reading 'headers') at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:261:61) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) in the console.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
victor
  • 134
  • 1
  • 9
  • I don't see any code in your examples that is attempting to read any `headers` property. Perhaps the issue is elsewhere? Is there an error stacktrace you could share with us that might indicate where the error is? It certainly seems that the `alert(`Response is ${res}`)` is working and that the error occurs *after* that. What debugging have you done from this point? – Drew Reese Jul 17 '23 at 19:32
  • I get the the alert from `res` in `auth.js` but the code proceeds with this else statement `alert("Login Failed")` – victor Jul 17 '23 at 19:39
  • What if you didn't use `alert` which blocks the main JS thread and used a `console.log` or breakpoint, or nothing at all and just let the code execute? – Drew Reese Jul 17 '23 at 19:40
  • I am getting the same results – victor Jul 17 '23 at 20:04

2 Answers2

2

To fix this error, you need to initialize the headers property on the NextResponse object before you return it. You can do this by using the headers property on the NextRequest object as a starting point. For example, you could do the following:

    const headers = request.headers;
    const newResponse = new NextResponse({
      body: Response,
      headers,
    });

    return newResponse;
0

After working on several trials, I found out this tutorial that explains using Next 13. I realized that the error was coming from not setting the headers in the response. After making some changes, here is my final code in the route.js

export async function POST(request) {
    const body = await request.json();
    const { email, password } = body;
    const bodystring = JSON.stringify({
        email,
        password
    });
    // console.log(`Posted data is: ${bodystring}`);
    try {
        const apiRes = await fetch(`${API_URL}/api/token/`, {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
            },
            body: bodystring
        })
        const data = await apiRes.json();
        // console.log(`Data is ${data}`)
        // console.log(`Response status is:${apiRes.status}`)
        if (apiRes.status === 200) {
            console.log("Login Succesful")
            const seralized = [
                cookie.serialize(
                    'access', data.access, {
                    httpOnly: true,
                    secure: false,
                    maxAge: 60 * 30,
                    sameSite: 'strict',
                    path: '/api/'
                }
                ),
                cookie.serialize(
                    'refresh', data.refresh, {
                    httpOnly: true,
                    secure: false,
                    maxAge: 60 * 60 * 24,
                    sameSite: 'strict',
                    path: '/api/'
                }
                )
            ];
            
            const response = {
                success: 'Logged in successfully'
            };
            return new Response(JSON.stringify(response), {
                status: 200,
                headers: { "Set-Cookie": seralized },
            });
        } else {
            // console.log("Login Failed")
            return NextResponse.status(apiRes.status).json({
                error: 'Authentication failed'
            });
            
        }
    } catch (error) {
        
    }
}
victor
  • 134
  • 1
  • 9