Welcome to the Kinde community

Updated 7 hours ago

Invalid Token Error

In my next.js application i am using next server actions for my api routes protected my kinde. I have mainly 4 routes get, get/id, edit and delete. All the routes work fine except the edit one where it gives me this error:
Plain Text
getUser Error [InvalidTokenError]
    at eval (webpack-internal:///(rsc)/./node_modules/jwt-decode/build/jwt-decode.esm.js:6:1134)
    at (rsc)/./node_modules/jwt-decode/build/jwt-decode.esm.js (C:\Users\harka\OneDrive\Documents\coding\paperless\.next\server\vendor-chunks\jwt-decode.js:40:1)
    at __webpack_require__ (C:\Users\harka\OneDrive\Documents\coding\paperless\.next\server\webpack-runtime.js:33:42)
    at eval (webpack-internal:///(rsc)/./node_modules/@kinde-oss/kinde-auth-nextjs/dist/server/index.js:15:68)
    at (rsc)/./node_modules/@kinde-oss/kinde-auth-nextjs/dist/server/index.js (C:\Users\harka\OneDrive\Documents\coding\paperless\.next\server\vendor-chunks\@kinde-oss.js:40:1)
    at __webpack_require__ (C:\Users\harka\OneDrive\Documents\coding\paperless\.next\server\webpack-runtime.js:33:42)
    at eval (webpack-internal:///(rsc)/./src/app/layout.js:13:93)
    at (rsc)/./src/app/layout.js (C:\Users\harka\OneDrive\Documents\coding\paperless\.next\server\app\receipts\[id]\page.js:489:1)
    at Function.__webpack_require__ (C:\Users\harka\OneDrive\Documents\coding\paperless\.next\server\webpack-runtime.js:33:42)   
    at async e9 (C:\Users\harka\OneDrive\Documents\coding\paperless\node_modules\next\dist\compiled\next-server\app-page.runtime.dev.js:35:396491)
    at async rU (C:\Users\harka\OneDrive\Documents\coding\paperless\node_modules\next\dist\compiled\next-server\app-page.runtime.dev.js:39:7365)
    at async r2 (C:\Users\harka\OneDrive\Documents\coding\paperless\node_modules\next\dist\compiled\next-server\app-page.runtime.dev.js:39:17560) {
  message: 'Invalid token specified'
}
 POST /api/receipts/edit/info/8r5WW52G455NpnRyW500 307 in 67ms
 POST /api/auth/login 405 in 16ms

Note that my kinde debug mode is set to true.
r
S
A
11 comments
Just to give an idea of my code and workflow im attaching the code

Modal.jsx worker method
Plain Text
const handleSubmitEditPayment = async (e) => {
    e.preventDefault();
    const formData = new FormData(e.target);

    formData.append("paymentInfo.method", method);
    formData.append("paymentInfo.status", status);

    await sendUpdateReceipt(id, formData)
      .then((result) => console.log(result))
      .catch((error) => console.log(error));
  };


sendUpdateReceipt.js
Plain Text
"use server";

import { getKindeServerSession } from "@kinde-oss/kinde-auth-nextjs/server";

export const sendUpdateReceipt = async (id, formData) => {
  try {
    const { getAccessTokenRaw } = getKindeServerSession();
    const token = await getAccessTokenRaw();

    const data = {};
    formData.forEach((value, key) => {
      data[key] = value; 
    });

    const response = await fetch(`http://localhost:3000/api/receipts/edit/${id}`, {
      method: "POST",
      headers: {
        "x-kinde-token": token,
        "Content-Type": "application/json"
      },
      body: JSON.stringify(data),
    });

    if (response.ok) {
      const result = await response.json();
      return result;
    } else {
      const errorResult = await response.json();
      return { error: errorResult.error };
    }
  } catch (error) {
    return {
      error,
    };
  }
};
middleware.js
Plain Text
import { NextResponse } from "next/server";
import { decode } from "jsonwebtoken";

export default async function middleware(req) {
  const token = req.headers.get("x-kinde-token");
  
  if (!token) {
    return NextResponse.json({ error: "No Token provided" }, { status: 401 });
  }

  const { header } = decode(token, { complete: true });

  const headersExist = header && Object.keys(header).length !== 0;

  if (!headersExist) {
    return NextResponse.json({ error: "Incorrect Token Provided" }, { status: 401 });
  }

  const requestHeaders = new Headers(req.headers);
  requestHeaders.set('x-kinde-header', JSON.stringify(header));
  requestHeaders.set('x-kinde-token', token);

  const response = NextResponse.next({
    request: {
      headers: requestHeaders,
    },
  });

  return response;
}

export const config = {
  matcher: ["/api/receipts/:path*"],
};


/api/receipts/edit/[id]/route.js

Plain Text
import { db } from "@/config/firebase";
import { getReceipt } from "@/helpers/getReceipt";
import { NextResponse } from "next/server";

export const POST = async (req, { params }) => {
  try {

    const data = await req.json();
    const receiptId = params.id;
    const receiptRef = db.collection("receipts").doc(receiptId);
    await receiptRef.update(data);

    const updatedReceipt = await getReceipt(receiptId)

    return NextResponse.json(
      {
        message: "Receipt updated successfully",
        receipt: updatedReceipt,
      },
      { status: 200 }
    );
  } catch (error) {
    console.log(error);
    return NextResponse.json(
      {
        error: "Error updating image",
      },
      { status: 400 }
    );
  }
};
    
I'm not familiar with Next.js sorry. But have you checked in DevTools that your app is sending across the exact same header for the edit requests as it is for the other requests? I don't believe Kinde is going to care what type of web method is called unless you're using API scopes.
Yes I am sending the exact same header for the edit requests. I’ve named it x-kinde-token . Even when I log the token in the middleware the token and tye resultant decoded header both get logged. And after the middleware I don’t really have a auth check for this route. So idk where is this extra getUser check being made and instead of a 200 I get a 405 method not allowed
Hi @readme ,

Thank you for providing the detailed context and code. I wanted to check in first—are you still facing the issue with the Invalid Token Error on the edit route?

If yes, here are a few clarifications and suggestions to help us troubleshoot further:

405 Method Not Allowed:
This indicates the HTTP method (POST) might not be recognized for the endpoint /api/auth/login. Could this request be redirecting incorrectly? If possible, log the request URL and headers on both client and server sides to confirm.

Token Decoding Issue:
Since you mentioned the token is logged successfully in middleware, the error could arise in subsequent steps (like token verification or backend usage). Have you verified if the token is valid at the exact point it’s passed to /api/receipts/edit/[id]?

Middleware Token Validation:
Could you confirm if the middleware is applying any additional restrictions (like roles or scopes) for the edit route that may differ from get, delete, etc.?

Kinde Debug Logs:
Since debug: true is enabled, any additional logs from Kinde’s SDK might give hints on where the invalid token check is happening.

Let me know if you need further assistance—I’d be happy to dig deeper
Yes i'm still facing that same issue. I also updated my next js to version 15. after logging the headers I am seeing the token and the headers begin logged. I am attaching the logged result.

Plain Text
import { NextResponse } from "next/server";
import { decode } from "jsonwebtoken";

export default async function middleware(req) {
  const token = req.headers.get("x-kinde-token");

  if (!token) {
    return NextResponse.json({ error: "No Token provided" }, { status: 401 });
  }

  const { header } = decode(token, { complete: true });
  if (!header) {
    return NextResponse.json({ error: "Invalid Token" }, { status: 401 });
  }

  // No redirects, just forward headers
  const requestHeaders = new Headers(req.headers);
  requestHeaders.set("x-kinde-header", JSON.stringify(header));
  requestHeaders.set("x-kinde-token", token);

  console.log(requestHeaders)

  return NextResponse.next({ request: { headers: requestHeaders } });
}


export const config = {
  matcher: ["/api/receipts/:path*"],
};
Attachment
image.png
i do not have any token verification configured for this route after the middleware stage. Also after updating as you can see the message has changed to getUser [TypeError: Cannot read properties of null (reading 'sub')]. Which could mean that the wherever this additiional step is taking place it is returing null after decoding the token.
after the middleware i directly have my route.js

Plain Text
import { db } from "@/config/firebase";
import { getReceipt } from "@/helpers/getReceipt";
import { NextResponse } from "next/server";

export const PUT = async (req, { params }) => {
  try {
    console.log(req)
    const data = await req.json();
    const receiptId = params.id;
    const receiptRef = db.collection("receipts").doc(receiptId);
    await receiptRef.update(data);

    const updatedReceipt = await getReceipt(receiptId)

    return NextResponse.json(
      {
        message: "Receipt updated successfully",
        receipt: updatedReceipt,
      },
      { status: 200 }
    );
  } catch (error) {
    console.log(error);
    return NextResponse.json(
      {
        error: "Error updating image",
      },
      { status: 400 }
    );
  }
};
    
i have also verified that the token is valid by copy pasting my token to the kinde jwt decoder website.
i've likely found the issue. after building the application using command npm run build i noticed that the /api/receipts/edit/[id] folder is not being included in the build. This could be the reason. What do you think?
Attachment
image.png
nvm i found the error @Ages @Stephen I named my file route..js instead of route.js. You can close this thread now. Thank you for your help.
Add a reply
Sign up and join the conversation on Discord