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
- Query Appwrite
Hello, I have a question regarding Queries in Appwrite. If I have a string "YYYY-MM", how can I query the $createdAt column to match this filter?
- Different appwrite IDs are getting expos...
File_URL_FORMAT= https://cloud.appwrite.io/v1/storage/buckets/[BUCKET_ID]/files/[FILE_ID]/preview?project=[PROJECT_ID] I'm trying to access files in my web app...
- Invalid document structure: missing requ...
I just pick up my code that's working a week ago, and now I got this error: ``` code: 400, type: 'document_invalid_structure', response: { message: 'Inv...