Back

How list endpoint filtering works?

  • 1
  • General
  • Tools
Abdulramon Jemil
29 Jun, 2023, 13:19

Okay, as I mentioned earlier, I'm using a proxy server. When a user makes a request to the proxy server and they are authenticated with the external auth system, I'll get their Auth token on the request object and verify it on the server. Appwrite allows setting user permissions regardless of whether the role exists or not. For example, I can set a collection permission like this 'write("user:273")', and appwrite will allow it even if the user with the id of 273 doesn't actually exist in my appwrite's user base. That's what I'm taking advantage of. So, I can just use any user id from an external auth system in my permission definition for any appwrite resource.

When the user makes the request, I verify their token, and get their id, and then, if the user is trying to access a document for example using the GetDocument endpoint, I'll fetch the collection, read it's permission field and see if the user's role is included in the read permissions. If it's there, I proxy the request directly to the user on the client. If not, I check if document security is enabled on the collection, if not, I return a 401, else, I fetch the document and see if it's permissions field includes a read permission for the user. If it does, I return the document, else, I return a 401.

This is just an overview of it, not how I actually plan to implement it.

Btw, I do all the fetches on the proxy server with API key Auth.

TL;DR
The user is discussing how list endpoint filtering works in Appwrite. They want to use a specific approach but need to disable direct client-side access for security reasons. The user is using Appwrite cloud, not a self-hosted version. Another user suggests blocking access to the Appwrite server from the outside as a security measure. To address the issue of filtering, the user suggests utilizing two features of Appwrite - Users and Teams. They suggest creating a second user inside Appwrite for each external Auth user and giving them all the same default password. They provide code examples for creating the user and obtaining the user JWT. Additionally, the
Abdulramon Jemil
29 Jun, 2023, 13:20

Back to the original question I asked though, I think it would be best to place some restrictions when taking my approach. I have defined some and I think they'll work well

Abdulramon Jemil
29 Jun, 2023, 13:21

Instead of having to carry out crazy relationship parsing and other stuff

Binyamin
29 Jun, 2023, 13:21

Gotcha.

Abdulramon Jemil
29 Jun, 2023, 13:28
Abdulramon Jemil
29 Jun, 2023, 13:34

Btw, I know not all appwrite endpoints need to be proxied, so only the necessary ones will be proxied

Abdulramon Jemil
29 Jun, 2023, 13:35

An endpoint like the locale get endpoint doesn't need the user to be authenticated via appwrite to function properly, so direct client side access to the locale service won't be blocked

Binyamin
29 Jun, 2023, 13:44

What you can do for this approach is to utilize two features of Appwrite

  • Users
  • Teams In such way that all the filtering process will be made for you by Appwrite.

Something like this

Create user

For each of your external Auth users create a second user inside Appwrite. Give all users the same default password.

TypeScript
const id = 1; // for example
const defaultPassword = 1234;

const promise = account.create(id, `${id}@example.com`, 'password');

Get the user JWT

To get Appwrite user JWT in a server side can be a bit tricky, so you'll need to use axios with some cookie jar and access the Account API by using the Account client REST API First install this package https://github.com/3846masa/axios-cookiejar-support#readme

Then you can have an axios clients that holds cookies

TypeScript
import axios from 'axios';
import { wrapper } from 'axios-cookiejar-support';
import { CookieJar } from 'tough-cookie';

const jar = new CookieJar();
const client = wrapper(axios.create({ jar }));

Now you'll need to request two endpoints

  • [POST] - /v1/account/sessions/email
    • For creating the session
  • [POST] - /v1/account/jwt
    • For getting user JWT.
TypeScript
const endpoint = 'https://cloud.appwrite.io';
const options = {
  headers: {
    'x-appwrite-project': 'projectID'
  }
};


async function getJWTOnServerSide(email, password) {
    try {
        // Log-in the user.
        await client.post(`${endpoint}/v1/account/sessions/email`, {email, password}, options);

        const res = await client.post(`${endpoint}/v1/account/jwt`, {} ,options);

        return res.data['jwt']
    } catch (e) {
        return '';
    }
}

Execute on behalf of the user

Now that you get the user JWT you can initialize a Server side client with the user JWT like so

TypeScript
const { Client } = require('node-appwrite');

const clientWithUser = new Client()
    .setEndpoint('https://cloud.appwrite.io/v1') 
    .setProject('[PROJECT_ID]')               
    .setJWT('Current user generated JWT');

Then when you'll use this client to run listDocuments you'll get only the documents that has permission to read.

TypeScript
const databases = new Databases(clientWithUser);

const promise = databases.listDocuments('[DATABASE_ID]', '[COLLECTION_ID]');
Abdulramon Jemil
29 Jun, 2023, 13:54

This requires direct client side access to be enabled, right?

Abdulramon Jemil
29 Jun, 2023, 13:54

Doesn't it?

Binyamin
29 Jun, 2023, 13:55

Yep, but you can block the access to that by blocking the access to your Appwrite server from the outside So the connection is isolated.

Abdulramon Jemil
29 Jun, 2023, 13:55

I don't get you

Binyamin
29 Jun, 2023, 13:56

Right now can any one expect your system cann acess Appwrite?

Abdulramon Jemil
29 Jun, 2023, 13:56

If direct client side access is enabled, then any body can actually guess the password I'm using for all users and do the same thing I'm doing on the server directly on the client, isn't that so. I think it is

Abdulramon Jemil
29 Jun, 2023, 13:57

Maybe, maybe not. But as a security measure, I can't assume that they won't know I'm accessing Appwrite

Binyamin
29 Jun, 2023, 13:58

Is this is not your infrastructure?

Abdulramon Jemil
29 Jun, 2023, 13:59

Yes, but for it to work, direct client side access must be disabled

Abdulramon Jemil
29 Jun, 2023, 13:59

And you approach requires direct client side access to be enabled

Binyamin
29 Jun, 2023, 14:00

Why you need it to be disabled? If you're using a Firewall that allow access to Appwrite only to your external server IP, then you can enjoy from both worlds.

Abdulramon Jemil
29 Jun, 2023, 14:00

By the way, I'm not using self hosted appwrite. I'm using Appwrite cloud

Binyamin
29 Jun, 2023, 14:02

Ohh, then I get the problem of using that approach.

Abdulramon Jemil
29 Jun, 2023, 14:07

It has to be disabled because if it isn't, users will be able to make direct requests to it.

This is required because I need appwrite to ignore whatever permissions I have defined, especially "user:userID" permissions since the user id is source from an external point. A user could create an appwrite account and get assigned an id that has been assigned to another user in my external system, and this, appwrite will process the user id and let the user that wasn't intended access to eventually get access

Abdulramon Jemil
29 Jun, 2023, 14:08

Yeah. Exactly...

Drake
30 Jun, 2023, 16:33

https://discord.com/channels/564160730845151244/1123704308966379552/1123972307057119273

I still like this approach since you can make use of Appwrite's permission system

Abdulramon Jemil
30 Jun, 2023, 16:59

Yeah, I really would love to use it too, but I later why it can't be used

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