
So, here is the problem, I want to get an user based on their credentials, the process a initially followed:
- Pass user email/password from a html form
- In server side, using node-appwrite with an api_key, make session token out .secret from 1, save it in a cookie
- I don't think I can use this cookie on my server instance, right? I get this: 'API key and session used in the same request. Use either setSession or setKey. Learn about which authentication method to use in the SSR docs: https://appwrite.io/docs/products/auth/server-side-rendering'
Is the correct approach just create another new Client() instance from Appwrite, just to grab this user information? And effectively checking permissions and such just when I'm making requests on DB, by always using a new Client() with an API key?
My objective with this is that: any data that is being saved on a Appwrite has to be sanitized in server side, for example, lets say that I want to save an username for a game character, it can't have any special symbols, only letter and numbers, without the server side validation, people can pass anything by just grabbing their .secret cookie and making direct requests for Appwrite.
PS I'm aware that the allowed characters in Appwrite are: alphanumeric, hyphen, non-leading underscore, period, but it's just to get an idea.

Here is some code:
// server instance, has an api key and full access, but can't use a session to grabe an user.
import { Account, Client, Databases } from 'node-appwrite';
import { API_KEY } from '$env/static/private';
import { PUBLIC_ENDPOINT, PUBLIC_PROJECT } from '$env/static/public';
const serverSession = new Client();
serverSession
.setEndpoint(PUBLIC_ENDPOINT)
.setProject(PUBLIC_PROJECT)
.setKey(API_KEY);
const account = new Account(serverSession);
const databases = new Databases(serverSession);
export { account, databases, serverSession }
// part of my login code, email and passwords comes from the frontend.
import { account } from '$lib/server/appwrite';
// ... more verification code ...
const { email, password } = result.data;
const res = await account.createEmailPasswordSession(email, password);
cookies.set('session', res.secret, {
path: '/',
httpOnly: true,
sameSite: 'strict'
});
// a hook, this run at each request, I can't grab the user here
const auth: Handle = async ({ event, resolve }) => {
const session = event.cookies.get('session');
if (!session) {
if (event.url.pathname !== '/login') throw redirect(303, '/login');
return await resolve(event);
}
try {
serverSession.setSession(session);
const user = await account.get();
console.log(user);
event.locals.user = user;
} catch (error) {
event.cookies.delete('session', { path: '/' });
if (event.url.pathname !== '/login') throw redirect(303, '/login');
}
return await resolve(event);
};

What framework are you using for your website?

it seems like you are using next.js?

Sveltekit

ahh

So, what you should do is the following:
- Login -> create cookie
- With cookie -> get value from cookie on the server, which should only have the value, use .setSession(tokenHere) as your client

I see you are using .setKey

For example in my project (next.js, but same principle):
const headersList = headers()
const cookieHeader = headersList.get('cookie')
const cookies = cookieHeader ? cookieHeader.split('; ') : []
const sessionCookie = cookies.find((cookie) =>
cookie.startsWith(
`a_session_${process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID}`
)
)
const client = new Client()
.setEndpoint(`${process.env.NEXT_PUBLIC_API_URL}/v1`)
.setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID)
if (sessionCookie) {
client.setSession(sessionCookie.split('=')[1])
}

what you are saying is, from what I said:
Is the correct approach just create another new Client()... etc, etc, etc
is this correct?

you are saying i shoudl create a new client instance just to grab this data

You should grab the cookie and then set a client instance

The thing about SSR, is nothing is saved client side.
So what I do:
export async function createSessionServerClient() {
const headersList = headers()
const cookieHeader = headersList.get('cookie')
const cookies = cookieHeader ? cookieHeader.split('; ') : []
const sessionCookie = cookies.find((cookie) =>
cookie.startsWith(
`a_session_${process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID}`
)
)
const client = new Client()
.setEndpoint(`${process.env.NEXT_PUBLIC_API_URL}/v1`)
.setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID)
if (sessionCookie) {
client.setSession(sessionCookie.split('=')[1])
}
return {
get account() {
return new Account(client)
},
get teams() {
return new Teams(client)
},
get databases() {
return new Databases(client)
},
get storage() {
return new Storage(client)
},
get functions() {
return new Functions(client)
},
get messaging() {
return new Messaging(client)
},
get locale() {
return new Locale(client)
},
get avatars() {
return new Avatars(client)
},
}
}
And then on every page, let's say you want to use database:
const { databases } = await createSessionServerClient()

So for each request you are making with "databases", you make sure to set the client, which the token you basically get from your cookie

huhum...

so, i should have something like, sessionClient and adminClient, each a different new Client() instance, being adminClient one that has setKey

Yes

i see

This is how my entire appwrite-session.ts file looks like:

createSessionClient is the same as createSessionServerClient, but it uses request as a parameter for the /api routes, which is basically CSR -> SSR -> SSR, but that's kind of a special case..

but you can see the createAdminSession and createSessionServerClient

i see, this makes sense, I had some misconceptions, but this cleared it

thanks a lot

Great to hear!
If this solved your issue, please add [SOLVED] at the beginning of the title.
Happy appwriting! :appwriterocket:
Recommended threads
- my database attribute stuck in processin...
when i created attributes in collection 3 of those attributes become "processing", and they are not updating, the worst thing is that i cant even delete them s...
- Is Quick Start for function creation wor...
I am trying to create a Node.js function using the Quick Start feature. It fails and tells me that it could not locate the package.json file. Isn't Quick Start ...
- Forever Processing Issue
I encountered an issue when creating attributes in the collections . if you create an attribute of type string for example and choose a size of 200 or 250 or a...
