Dev manual is contradicting re: OCS versus REST

The OCS OpenAPI tutorial in the dev manual says

PREFER to expose your APIs using OCS

It provides a more standardized and easier way to write your APIs. Other methods are considered legacy. For details take a look at OCS.

Two examples are shown:

// "Bad" example
class SomeController extends ApiController {...}
// "Good" example
class SomeController extends OCSController {...}

But if you follow the mentioned OCS link, it says

OCS

NOTE
This is purely for compatibility reasons. If you are planning to offer an external API, go for a REST APIs instead.

Following the REST APIs link now tells you

REST APIs

Offering a RESTful API is not different from creating a route and controllers for the web interface. It is recommended though to inherit from ApiController and add @CORS annotations to the methods so that web applications will also be able to access the API.

with the following example

class AuthorApiController extends ApiController {...}

which is essentially the so called “Bad” example from above.

So which way is the recommended way now?

  1. Extending the ApiController and putting the API routes into the routes key inside routes.php or
  2. extending the OCSController and putting the API routes into the ocs key inside routes.php?

OK, I know the documentation is not really good there. (remind myself to extend this). I try to explain as much as I can about it.

Note that REST is not CORS. We are comparing in fact 3 different things here:

  1. REST-based access (without CORS enabled) to get data from the backend to the frontend of the app
  2. Using OCS to get data from the backend to the frontend or other apps of the user
  3. Using REST with CORS enabled to get data from the backend to external hosts

Note that if you read carefully, you will find that 1 is considered legacy over 2. This is also true as the NC internal openapi app works better (explanation below) with 2 than with 1.

So far we only exchanged data with the forntend of the NC instance. This has the benefit that the host is the same as the backend which disables some browser-embedded security features (CORS). Once we leave this assumption, new considerations come to play.

If the client is a native app or something in this direction (no Webapp!) 1 and 2 are equal in terms of security but again 2 is in favor of having a cleaner structure.

If the client is a foreign webapp, things gets more complicated. Now, CORS must be enabled, which is true for 3 and 2 (2 makes this by default). So, with 2 you are good to go and done if that works. However, the additional encapsulation is something more or less NC-specific. So, if you want to provide data to third parties in a dedicated format, you will have to fall back to solution 3 (to allow external web applications to access the data).


One point on the preference of 2 over 1:
If you want to allow both the web frontend and external apps to access the endpoints, you have the problem that you want to have one endpoint with CSRF enabled (a cookie set by the server frontend is required for the request to succeed to prevent scripting attacks on the frontend). This is used for the frontend access.
For the external app access (both web and native), the CSRF must be disabled rendering these endpoints more vulnerable by definition. The endpoint can have CORS enabled at no additional cost.
If you used the external endpoint with the web frontend you have multiple issues to address/think of:

  1. The CSRF check is not active. OK, it will work but this is a small security weakening that might trigger more severe issues.
  2. The request to a CORS endpoint will invalidate the session. This is a security measurement to enforce transmission of a password/token every time. Your user will get logged of in this case.

With OCS you get everything in one single controller.

I have to admit, this is not by design of the security measures but how these are implemented and what seemed the best solution in average. I do not want to criticize here just state the facts.

Long story short: If you have no special requirements, go with OCS and benefit from the work done for you already.

Thanks for the explanation.

One last question:
I’m not planning to expose the API to third parties. The API is only consumed by the frontend of the same app, i.e. I’m writing both the frontend and backend. Am I right to assume that in this case I should extend the generic OCP\AppFramework\Controller?

As I said: If there is no requriement to go with anything special (I guess your case is so), I would go with OCS. Honestly, I am planning to migrate from REST to OCS in the longer run. But you are the decv so you can do what you think best. The generic Controller is in fact one (good (?)) alternative solution to OCS.

Christian