
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
- Dockerizing Appwrite Console Yields Page...
I have this Docker Compose file: ``` services: # Band9Buddy app band9buddy: build: context: . dockerfile: Dockerfile.dev develop: ...
- Upgrading Appwrite 1.7.4 → 1.8.x: What H...
I'm currently running a self-hosted Appwrite v1.7.4 instance that still uses the old Collections/Documents database model. I noticed that starting from v1.8.x,...
- Domain not working
My domain [fork-fable.appwrite.network](https://fork-fable.appwrite.network/) returns a 500 even after deleting and redeploying. Other domains added in domains ...
