You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: developer_manual/basics/controllers.rst
+24-2Lines changed: 24 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -393,6 +393,10 @@ A :doc:`template <front-end/templates>` can be rendered by returning a TemplateR
393
393
394
394
}
395
395
396
+
Showing a template is the only exception to the rule to :ref:`not disable CSRF checks <csrf_introduction>`:
397
+
The user might type the URL directly (or use a browser bookmark or similar) to navigate to a HTML template.
398
+
Therefore, usage of the ``#[NoCSRFRequired]`` attribute (see :ref:`below<controller_authentication>`) is acceptable in this context.
399
+
396
400
Public page templates
397
401
^^^^^^^^^^^^^^^^^^^^^
398
402
@@ -434,6 +438,11 @@ A ``OCP\\AppFramework\\Http\\Template\\SimpleMenuAction`` will be a link with an
434
438
developers can implement their own types of menu renderings by adding a custom
435
439
class implementing the ``OCP\\AppFramework\\Http\\Template\\IMenuAction`` interface.
436
440
441
+
As the public template is also some HTML template, the same argumentation as for :ref:`regular templates<controller_template>` regarding the CSRF checks hold true:
442
+
The usage of ``#[NoCSRFRequired]`` for public pages is considered acceptable for some pages:
443
+
Each page that the user should be able to directly access (by typing/pastig the URL in the browser or clicking on a link in a mail) should have this attribute set.
444
+
For multi-page forms in the second and later stages, this should **not** be set as the user should follow the series of pages.
445
+
437
446
Data-based responses
438
447
--------------------
439
448
@@ -448,10 +457,14 @@ The user only indirectly requested the data by user interaction with the fronten
448
457
OCS
449
458
^^^
450
459
460
+
In order to simplify exchange of data between the Nextcloud backend and any client (be it the web frontend or whatever else), the OCS API has been introduced.
461
+
Here, JSON and XML responders have been prepared and are installed without additional effort.
462
+
451
463
.. note::
452
-
This is purely for compatibility reasons. If you are planning to offer an external API, go for a :ref:`REST APIs <rest-apis>` instead.
464
+
The usage of OCS is closely related to the usage of :doc:`../digging_deeper/rest_apis`.
465
+
Unless you have a clear use-case, it is advised to use OCS over pure REST.
466
+
A more detailed description can be found in :ref:`ocs-vs-rest`.
453
467
454
-
In order to simplify exchange of data between the Nextcloud backend and any client (be it the web frontend or whatever else), the OCS API has been introduced.
455
468
To use OCS in your API you can use the **OCP\\AppFramework\\OCSController** base class and return your data in the form of a **DataResponse** in the following way:
456
469
457
470
.. code-block:: php
@@ -509,6 +522,10 @@ Now your method will be reachable via ``<server>/ocs/v2.php/apps/<APPNAME>/api/v
509
522
JSON
510
523
^^^^
511
524
525
+
.. warning::
526
+
The usage of standard controller to access content data like JSON (no HTML) is considered legacy.
527
+
Better use :ref:`OCS <ocscontroller>` for this type of requests.
528
+
512
529
Returning JSON is simple, just pass an array to a JSONResponse:
513
530
514
531
.. code-block:: php
@@ -547,6 +564,11 @@ Because returning JSON is such a common task, there's even a shorter way to do t
547
564
548
565
Why does this work? Because the dispatcher sees that the controller did not return a subclass of a Response and asks the controller to turn the value into a Response. That's where responders come in.
549
566
567
+
.. deprecated:: 30
568
+
569
+
Usage of "index.php"-controllers for data transmission should be avoided. Use OCS instead.
Copy file name to clipboardExpand all lines: developer_manual/digging_deeper/rest_apis.rst
+147-2Lines changed: 147 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,8 @@ REST APIs
6
6
7
7
.. sectionauthor:: Bernhard Posselt <dev@bernhard-posselt.com>
8
8
9
-
Offering a RESTful API is not different from creating a :doc:`route <../basics/routing>` and :doc:`controllers <../basics/controllers>` for the web interface. It is recommended though to inherit from ApiController and add ``#[CORS]`` attribute to the methods so that `web applications will also be able to access the API <https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS>`_.
9
+
Offering a RESTful API is not different from creating a :doc:`route <../basics/routing>` and :doc:`controllers <../basics/controllers>` for the web interface.
10
+
It is recommended though to inherit from ApiController and add ``#[CORS]`` attribute to the methods so that `web applications will also be able to access the API <https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS>`_.
10
11
11
12
.. code-block:: php
12
13
@@ -44,7 +45,8 @@ CORS also needs a separate URL for the preflighted **OPTIONS** request that can
44
45
)
45
46
46
47
47
-
Keep in mind that multiple apps will likely depend on the API interface once it is published and they will move at different speeds to react to changes implemented in the API. Therefore it is recommended to version the API in the URL to not break existing apps when backwards incompatible changes are introduced::
48
+
Keep in mind that multiple apps will likely depend on the API interface once it is published and they will move at different speeds to react to changes implemented in the API.
49
+
Therefore it is recommended to version the API in the URL to not break existing apps when backwards incompatible changes are introduced::
48
50
49
51
/index.php/apps/myapp/api/1.0/resource
50
52
@@ -79,3 +81,146 @@ To add an additional method or header or allow less headers, simply pass additio
79
81
}
80
82
81
83
}
84
+
85
+
.. _ocs-vs-rest:
86
+
87
+
Relation of REST and OCS
88
+
------------------------
89
+
90
+
There is a close relationship between REST APIs and :ref:`OCS <ocscontroller>`.
91
+
Both provide a way to transmit data between the backend of the app in the Nextcloud server and some frontend.
92
+
This is explicitly not about :ref:`HTML template responses <controller_html_responses>`.
93
+
94
+
State-of-the-Art methods and comparison
95
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
96
+
97
+
The following combinations of attributes might be relevant for various scenarios:
98
+
99
+
#. Plain frontend route: ``Controller`` class
100
+
#. OCS route: ``OCSController`` class
101
+
#. OCS route with CORS enabled: ``OCSController`` class and ``#[CORS]`` attribute on the method
102
+
103
+
.. warning::
104
+
Adding the ``#[NoCRSFRequired]`` attribute imposes a security risk.
105
+
You should not add this to your controller methods unless you understand the implications and be sure that you absolutely need the attribute.
106
+
Typically, you can use the ``OCS-APIRequest`` header for data requests instead, in order to satisfy the CSRF checks in your API requests.
107
+
108
+
.. warning::
109
+
Adding the attribute ``#[CORS]`` alone is not sufficient to allow access using CORS with plain frontend routes.
110
+
Without further measures, the CSRF checker would fail.
111
+
So, enabling CORS for plain controllers is generally and highly discouraged.
112
+
113
+
You would have to disable the CSRF checks (one more security risk) or use the ``OCP-APIRequest`` header or send a CSRF token to successfully pass the checks.
114
+
The latter requires dedicated JS code on the importing page.
115
+
116
+
There are different ways a clients might interact with your APIs.
117
+
These ways depend on your API configuration (what you allow) and on which route the request is finally made.
118
+
119
+
- *Access from web frontend* means the user is accessing the Nextcloud web frontend with a web browser.
120
+
- *Access from non-browser* is if the user accesses the resource or page using something that is not a web browser, like an Android app or a curl command.
121
+
- *Access from external website* means that the user browses some third party web site and data from your Nextcloud server appears.
122
+
The other website has to embed/load/use images, JSON data, or other resources from a URL pointing to the Nextcloud server, to be able to do this.
123
+
124
+
.. hint::
125
+
The discussion here is for data requests only.
126
+
If you think of controller :ref:`methods serving (HTML) templates <controller_html_responses>`, disabling CSRF is considered fine.
127
+
128
+
.. list-table:: Comparison of different API types
129
+
:header-rows: 1
130
+
:align: center
131
+
132
+
* - Description
133
+
- ``Controller`` class
134
+
- ``OCSController`` class
135
+
- ``OCSController`` class & ``CORS`` on method
136
+
* - URL prefix (relative to server)
137
+
- ``/apps/<appid>/``
138
+
- ``/ocs/v2.php/apps/<appid>/``
139
+
- ``/ocs/v2.php/apps/<appid>/``
140
+
* - Access from web frontend
141
+
- yes
142
+
- yes
143
+
- yes
144
+
* - Access from non-browser
145
+
- partial [#]_
146
+
- yes
147
+
- yes
148
+
* - Access from external website
149
+
- no
150
+
- no
151
+
- yes
152
+
* - Encapsulated data
153
+
- no
154
+
- yes (JSON or XML)
155
+
- yes (JSON or XML)
156
+
157
+
.. [#] The external app has to satisfy the CSRF checks.
158
+
That is, you need to have the ``OCS-APIRequest`` HTTP request header set to ``true``.
159
+
This is only possible for Nextcloud 30 onwards, older versions do not respect the header.
160
+
161
+
Methods from ``Controller`` classes can return ``DataResponse`` objects similar to ``OCSController`` class methods.
162
+
For methods of a ``Controller`` class, the data of this response is sent e.g. as JSON as you provide it.
163
+
Basically, the output is very similar to what ``json_encode`` would do.
164
+
In contrast, the ``OCSController`` will encapsulate the data in an outer shell that provides some more (meta) information.
165
+
For example a status code (similar to the HTTP status code) is transmitted at top level.
166
+
The actual data is transmitted in the ``data`` property.
167
+
168
+
As a rule of thumb one can conclude that OCS provides a good way to handle most use cases including sufficient security checks.
169
+
The only exception to this is if you want to provide an API for external usage where you have to comply with an externally defined API scheme.
170
+
Here, the encapsulation introduced in OCS and CSRF checks might be in your way.
171
+
172
+
173
+
Historical options
174
+
~~~~~~~~~~~~~~~~~~
175
+
176
+
.. deprecated:: 30
177
+
The information in this section are mainly for reference purposes. Do not use the approaches in new code.
178
+
179
+
Before Nextcloud 30 the plain ``Controller`` classes' methods did not respect the ``OCS-APIRequest`` header.
180
+
Thus, to provide access to this type of controller methods for external apps, it was necessary to use the ``#[NoCSRFRequired]`` attribute (or the corresponding ``@NoCSRFRequired`` annotation).
181
+
182
+
The following combinations of attributes were relevant for various scenarios:
183
+
184
+
#. Plain frontend route: ``Controller`` class
185
+
#. Plain frontend with CRSF checks disabled: ``Controller`` class and ``#[NoCSRFRequired]`` attribute on the method
186
+
#. Plain frontend route with CORS enabled: ``Controller`` class and ``#[CORS]`` and ``#[NoCSRFRequired]`` attributes on the route
187
+
#. OCS route: ``OCSController`` class
188
+
#. OCS route with CORS enabled: ``OCSController`` class and ``#[CORS]`` attribute on the method
189
+
190
+
.. hint::
191
+
The two scenarios involving the ``OCSController`` have not changed and, thus, the state-of-the-art documentation as noted above still holds true.
192
+
Thus, these options are not reconsidered here again for simplicity reasons and to get the overall view more crisp.
193
+
194
+
The warnings about not using ``NoCSRFRequired`` and ``CORS`` as mentioned in the state-of-the-art section holds true here as well.
Copy file name to clipboardExpand all lines: developer_manual/prologue/security.rst
+30-2Lines changed: 30 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -213,10 +213,12 @@ Sensitive data exposure
213
213
214
214
Always store user data or configuration files in safe locations, e.g. **nextcloud/data/** and not in the webroot where they can be accessed by anyone using a web browser.
215
215
216
+
.. _csrf_introduction:
217
+
216
218
Cross site request forgery
217
219
--------------------------
218
220
219
-
Using `CSRF <https://en.wikipedia.org/wiki/Cross-site_request_forgery>`_ one can trick a user into executing a request that they did not want to make. Thus every POST and GET request needs to be protected against it. The only places where no CSRF checks are needed are in the main template, which is rendering the application, or in externally callable interfaces.
221
+
Using `CSRF <https://en.wikipedia.org/wiki/Cross-site_request_forgery>`_ (see also on `MDN <https://developer.mozilla.org/en-US/docs/Glossary/CSRF>`__) one can trick a user into executing a request that they did not want to make. Thus every POST and GET request needs to be protected against it. The only places where no CSRF checks are needed are in the main template, which is rendering the application, or in externally callable interfaces.
220
222
221
223
.. note:: Submitting a form is also a POST/GET request!
222
224
@@ -227,7 +229,11 @@ To prevent CSRF in an app, be sure to call the following method at the top of al
227
229
<?php
228
230
OCP\JSON::callCheck();
229
231
230
-
If you are using the App Framework, every controller method is automatically checked for CSRF unless you explicitly exclude it by setting the ``#[NoCSRFRequired]`` attribute or ``@NoCSRFRequired`` annotation before the controller method, see :doc:`../basics/controllers`
232
+
If you are using the App Framework, every controller method is automatically checked for CSRF unless you explicitly exclude it by setting the ``#[NoCSRFRequired]`` attribute or ``@NoCSRFRequired`` annotation before the controller method, see :doc:`../basics/controllers`.
233
+
234
+
Additionally, it is advised to carefully select the HTTP method used for requests.
235
+
Requests of type ``GET`` should not alter data but just read existing data.
236
+
This way, at least no typed (or copied) URL might alter data (e.g. clicking a link from a spam mail message by accident).
231
237
232
238
Unvalidated redirects
233
239
---------------------
@@ -250,6 +256,28 @@ Always validate the URL before redirecting if the requested URL is on the same d
`Cross-origin resource sharing (CORS) <https://en.wikipedia.org/wiki/Cross-origin_resource_sharing>`_ (see also on `MDN <https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS>`__) is a method implemented by browser to access resources from different domains at the same time.
264
+
Assume, there is a website published on host A.
265
+
The URL would for example be ``https://A/path/to/index.html``.
266
+
If there is a _different_ host B that serves a resource (e.g. an image file) as ``https://B/assets/image.jpg``, the index file on host A could simply link to the image on B.
267
+
However, to protect B and its property (the image), the browsers do not silently embed the image of B into the page of A.
268
+
Instead, B is kindly asked by the browser if embedding is allowed (the so-called `preflight <https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request>`_).
269
+
270
+
To do so, there is a first request made to the resource on B with the ``OPTIONS`` HTTP command/verb.
271
+
The server only answers with the headers as specified and adds ``Access-Control-*`` headers.
272
+
These define, what the browser is to be allowed to do.
273
+
Only if the destination server B confirms cross site resource sharing is allowed, the browser access the resource.
274
+
275
+
Basically, accessing foreign resources is not limited to embedding images.
276
+
Using JavaScript, arbitrary XHR/Ajax requests can be directed at arbitrary other hosts, which might be used to call APIs that leak your data.
277
+
There are some safety measurements in place (especially about cookie handling), but one has still to be careful not to leak information unwillingly.
278
+
Especially, if the destination server B allows to sent credentials using ``Access-Control-Allow-Credentials: true``, cross site scripting is very critical.
279
+
You need :ref:`CSRF protection <csrf_introduction>` in place or your users are at relatively high risk.
0 commit comments