Who can call a public function?

Hello,

I am trying to understand what exactly the private config of a function means?
I understand that if the function is private then client applications as a whole won’t be able to access the function.
But if private = false does it mean that a non-authenticated user in the app will be able to call this function?
I want to make sure that the function is not exposed to non-authenticated requests…

Hi, I think the description in the UI is relatively good (not sure if you saw it)

If private, this function may be called from incoming webhooks, rules, and other functions defined in the App Services console. Private functions may not be called from client applications.

The idea is just that if you define a function as private it is only callable by other parts of app services (almost like declaring a function private). So that would mean only things like triggers, rules, webhooks, etc can call the function.

Making the function public means that external users can hit the client-api and run the function, but authentication and authorization are still performed as configured by the application.

Best,
Tyler

@Tyler_Kaye
Thanks,
Yes, I read the docs several times and it is unclear, the “private” is very clear, the “public” isn’t.
One can understand “public” as “anyone can call it regardless of authentication”, so where is it exactly that I define that only authenticated users can execute a public function? Because even the “Authentication” section in the function settings is confusing (it is more “delegated permissions” than “Authentication”).
So, if I need my function to “run as system” but be accessible only by authenticated users, where do I define it?

Wanted to let you know I have forwarded this along to an engineer on the relevant team who will hopefully reach out soon about it. I believe the TLDR is that defining the function as public just means that it is accessible via the Client API.

Running as a system user is a separate setting without any relationship to the public/private nature of the function. https://www.mongodb.com/docs/atlas/app-services/users/#system-user

@Tyler_Kaye
Thx.
I tried to replay an http request to a public function and removed the “Authorization” header, I got an error, this is good, but I would like to make sure this is the intendent behavior…

That sounds like the correct behaviour to me. Similarily if you change the header it will fail because it is not an authenticated user/token.

Hi @YuvalW , if it helps I would think of the private setting as separate from the Authentication section.

If a function is not set to private, it can be called via the client api as Tyler mentioned. If it is private, then it cannot be called via the client API. This is currently the only restriction that the private setting is applied to

Authentication is separate. Regardless if a function is private or not, the authentication piece determines if the caller is allowed to execute the function. For example, if the function is tied to an HTTPS Endpoint and authentication is set to “System”, then anybody can call the HTTPS Endpoint and invoke the function. The System setting also bypasses data access permissions which is likely not what you want.

To answer your use case, you could create a function that is set to “System” authentication and create another function that uses Application Authentication that calls the first function. Does that solve your use case?

Hi @Kush_Patel,
“If a function is not set to private, it can be called via the client api” - That is my case, now what I am asking is WHO can call it via the client api? is it guaranteed that only logged-in users will be able to call this function?
I do NOT expose my functions via https endpoints, I see that the client api is making a POST request to:

https://us-east-1.aws.realm.mongodb.com/api/client/v2.0/app/my-app-name-zdgtm/functions/call

Is it guaranteed that only authenticated users will be able to invoke that api above?

Hi @YuvalW ,

Any request to that functions/call API endpoint MUST be authenticated or the request will error with a 401. So you can be guaranteed that the above endpoint will only invoke the function if the request is authenticated i.e. the user must be logged in/pass the correct credentials. Does that answer you question?

Thank you @Kush_Patel, yes, that answers my question.

Now if we are at it I want to ask a question to your comment:

The System setting also bypasses data access permissions which is likely not what you want.

As I understand it, if I don’t use System permissions it means that I have to grant the end-users access to the collections (via the data access permissions).
Now I am developing a sort of an “admin” protal, where I just want the users to be able to fetch specific reports, I don’t like the idea of letting the users read access to the collections, that’s why I want no one to have access to the data aside for the backend functions.
Does it make sense to do what I do or is there another more secure way to acheive this?

Hi @YuvalW ,

Your approach sounds correct to me. Using Application Auth in combination with Rules should solve your use case. You can add a rule on the collection that allows access to certain documents/fields depending on the Apply When permissions of the roles that are configured on the rule.

For example, if you have a rule configured for collection “foo” that only allows reads and has an Apply When expression that is always true, then users that are authorized to invoke your function will only be able to see documents that the function returns. They won’t have read-only access to the “foo” collection outside of a function that queries collection “foo” in this case. You can also experiment with more restrictive Apply When expressions to only return specific fields/documents depending on the user calling the function, depending on your use case

@Kush_Patel Not sure I follow, I started with this approach, where I have collection “foo” and I setup a role with “readAll” permission.
The problem is that in the client the user could do as below and read all docs (directly from the client).

let mongo = realmApp.user.mongoClient('my-cluster');
let res = await mongo.db('my-db').collection('foo').find({});

is there an “apply when” rule that allows a “Read” access only if the read is being done from a function? (and not client).

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.