Back

JWT created from an OAuth Account doesn't work

  • 0
  • Self Hosted
  • Accounts
  • Web
Ninjonik
22 Feb, 2024, 17:31

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:

TypeScript
{ 
  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:

TypeScript
{
  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.

TL;DR
Developers are confused about why .createJWT() returns an object instead of a string. The JWT was regenerated and is different. The issue may be related to passing an object when it should be a JWT string and logging databases.client.headers may help. Double-check the JWT before calling client.setJWT(jwt) and make sure it is correct. Using client.setKey(jwt) instead of client.setJWT(jwt) causes a "user_unauthorized" error. The solution might be to check the JWT generation process and ensure it is returning a string. It is advised to verify the JWT before setting it with client.setJWT(jwt).
Ninjonik
22 Feb, 2024, 17:32

My current setup: appwrite-jwt.ts:

TypeScript
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:

TypeScript
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 })
        }
}
Steven
22 Feb, 2024, 17:32

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

Ninjonik
22 Feb, 2024, 17:32

yes, it is correct

Ninjonik
22 Feb, 2024, 17:34

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

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

Steven
22 Feb, 2024, 17:34

what is exactly throwing the error?

Ninjonik
22 Feb, 2024, 17:34

the client.setJWT(jwt);

Steven
22 Feb, 2024, 17:35

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

Ninjonik
22 Feb, 2024, 17:35

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

Ninjonik
22 Feb, 2024, 17:36

it is the return await databases.createDocument()

Steven
22 Feb, 2024, 17:37

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

Ninjonik
22 Feb, 2024, 17:38
TypeScript
{
  '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'
  }
}
Ninjonik
22 Feb, 2024, 17:38

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

Steven
22 Feb, 2024, 17:39

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

Ninjonik
22 Feb, 2024, 17:44

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?

Reply

Reply to this thread by joining our Discord

Reply on Discord

Need support?

Join our Discord

Get community support by joining our Discord server.

Join Discord

Get premium support

Join Appwrite Pro and get email support from our team.

Learn more