
Hello,
I am using appwrite and I need to pass client's jwt to an api route so that api route can make additional validations on the server meanwhile only being in the scope of local user's permissions.
Now we are using OAuth to authenticate our users, problem is that when I generate a JWT token like this:
const jwt = await account.createJWT()
- this is on the client
it returns a normal valid token like this: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiI2NWQwZjZiMjQ4YzMwMTdiNzA3YSIsInNlc3Npb25JZCI6IjY1ZDEwMzFkNDQzYWJkMmM2MDBiIiwiZXhwIjoxNzA4NjIzMjY1fQ.V46zLFgFf3XQR0zUxK6XtTxjJUVBMEnowW5ZJBSDT7s
However when I try to do something with the token like this:
client.setJWT(jwt);
- this is inside of the api route
I get the following error:
{
code: 401,
type: 'user_jwt_invalid',
response: {
message: 'Failed to verify JWT. Invalid token: Incomplete segments',
code: 401,
type: 'user_jwt_invalid',
version: '1.4.9'
}
}
I've seen some older post where someone suggested to use client.setKey(jwt) instead of the client.setJWT(jwt), however in that case I get the following error:
{
code: 401,
type: 'user_unauthorized',
response: {
message: 'Permissions must be one of: (any, guests)',
code: 401,
type: 'user_unauthorized',
version: '1.4.9'
}
}
I really have no idea what this is causing, hope to see your ideas soon.

My current setup: appwrite-jwt.ts:
import {Client, Databases, Functions, Users} from 'node-appwrite';
const appwriteEndpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT;
const appwriteProject = process.env.NEXT_PUBLIC_APPWRITE_PROJECT;
export const client = new Client();
if (appwriteEndpoint && appwriteProject) {
client
.setEndpoint(appwriteEndpoint)
.setProject(appwriteProject)
} else {
console.error("Please make sure APPWRITE_ENDPOINT APPWRITE_PROJECT are defined in your environment variables.");
}
export const users = new Users(client);
export const database = process.env.NEXT_PUBLIC_APPWRITE_DB_NAME ?? 'appwrite'
export const databases = new Databases(client);
export const functions = new Functions(client)
api route:
import {NextApiRequest, NextApiResponse} from 'next';
import {ID, Permission, Role} from 'node-appwrite';
import {client, database, databases} from "@/app/lib/appwrite-jwt";
const saveWuilting = async ({ text, words } : { text: string, words: number }) => {
try {
return await databases.createDocument(
...
);
} catch (error) {
...
} finally {
client.setJWT("");
}
};
export async function POST(req: Request, res: NextApiResponse) {
try {
...
client.setJWT(jwt);
...
} catch (error) {
console.error('Error saving wuilting:', error);
return Response.json({ error: 'Internal Server Error' }, { status: 500 })
}
}

before you call client.setJWT(jwt);
, can you print it and verify it's correct?

yes, it is correct

client: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiI2NWQwZjZiMjQ4YzMwMTdiNzA3YSIsInNlc3Npb25JZCI6IjY1ZDEwMzFkNDQzYWJkMmM2MDBiIiwiZXhwIjoxNzA4NjI0MDk2fQ.6AF_If6x3-VADSyUS26vQm0Bs1DMYX6PXiC-MzU50R0
api: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiI2NWQwZjZiMjQ4YzMwMTdiNzA3YSIsInNlc3Npb25JZCI6IjY1ZDEwMzFkNDQzYWJkMmM2MDBiIiwiZXhwIjoxNzA4NjI0MDk2fQ.6AF_If6x3-VADSyUS26vQm0Bs1DMYX6PXiC-MzU50R0

what is exactly throwing the error?

the client.setJWT(jwt);

that would not throw the error because it doesn't make any API call.

actually it doesn't, you are right, I debugged it wrong

it is the return await databases.createDocument()

right before that call, can you log databases.client.headers
?

{
'accept-encoding': '*',
'content-type': '',
'user-agent': 'AppwriteNodeJSSDK/11.1.0 (Windows_NT; Windows 10 Home; x64)',
'x-sdk-name': 'Node.js',
'x-sdk-platform': 'server',
'x-sdk-language': 'nodejs',
'x-sdk-version': '11.1.0',
'X-Appwrite-Response-Format': '1.4.0',
'x-appwrite-project': '65ca635fa446edba041b',
'x-appwrite-jwt': {
jwt: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiI2NWQwZjZiMjQ4YzMwMTdiNzA3YSIsInNlc3Npb25JZCI6IjY1ZDEwMzFkNDQzYWJkMmM2MDBiIiwiZXhwIjoxNzA4NjI0MzcyfQ.QNlZHkM0Fdde9D-WszOIRyuidlosFvqMw6A_srZl_bY'
}
}

(the jwt got regenerated, thats why it is different)

you're passing an object, but it should just be the JWT string

I see ye, but isn't it rather confusing that the .createJWT() returns an object instead of a string? or is there a reason for that?
Recommended threads
- phantom relationships appear on parent c...
i have this bug were my past deleted collection apears as relationship to my parent collection. when i try to delete that relationship from parent it gives me e...
- Attribute stuck on proccessing
i tried creating a new attribute butits stuck on proccessing,i did a hard refresh,cleared cache everything but still stuck on proccessing,also in my functions w...
- Properly contained appwrite main app can...
Hello! We tried to reinstall our main self-hosted appwrite with a new method but the main app 2 mins after launch throw this error: ```2025/06/22 16:16:14 s...
