Skip to content

Commit 6b96eba

Browse files
committed
docs(developer): document app password scopes for app developers
Signed-off-by: Peter Ringelmann <peter.ringelmann@nextcloud.com>
1 parent e414900 commit 6b96eba

4 files changed

Lines changed: 151 additions & 0 deletions

File tree

‎developer_manual/basics/controllers.rst‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,8 @@ To turn off checks the following *Attributes* can be added before the controller
879879
* ``#[NoTwoFactorRequired]``: A user can access the page before the two-factor challenge has been passed (use this wisely and only in two-factor auth apps, e.g. to allow setup during login)
880880
* ``#[NoCSRFRequired]``: Don't check the CSRF token (use this wisely since you might create a security hole; to understand what it does see :ref:`CSRF in the security section <csrf_introduction>`)
881881

882+
App passwords that a user limited to some parts of their account can't call any method by default, unless the user granted the whole app. To open single methods to them, see :doc:`../digging_deeper/app_password_scopes`.
883+
882884
.. note::
883885

884886
The attributes are only available in Nextcloud 27 or later. In older versions annotations with the same names exist:
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
===================
2+
App password scopes
3+
===================
4+
5+
.. versionadded:: 36
6+
7+
Since Nextcloud 36, users can limit an app password to some parts of their account,
8+
for example only Files or only Calendar. Each part is a *scope*, a string like
9+
``files:files:read``. Users pick them in *Settings > Security > Devices & sessions*
10+
by choosing *Custom* access.
11+
12+
A limited app password can't use your app's API or DAV collections until the user grants
13+
your whole app, or you add scopes to your controller methods. App passwords with full
14+
access and browser sessions work as before.
15+
16+
Closed by default
17+
-----------------
18+
19+
A limited app password can't reach:
20+
21+
* Controller methods without a scope attribute. They are refused with ``403`` (over OCS
22+
v1, in the OCS status of the response).
23+
* Pages. A ``TemplateResponse`` is refused, even if the method has a scope.
24+
* Admin-only methods, even when the user is an admin. A method counts as admin-only
25+
when it has none of ``#[NoAdminRequired]``, ``#[SubAdminRequired]`` and ``#[PublicPage]``.
26+
* Your app's DAV collections, see `Opening DAV collections`_.
27+
28+
Granting a whole app
29+
--------------------
30+
31+
If your app has an entry in the app menu, it works with a limited app password without
32+
any changes, as long as the user limits it to your whole app. The app password then
33+
stores your app ID, like ``deck``, and can use your controller methods and DAV
34+
collections, with or without ``#[TokenScope]``. Pages and admin-only methods stay closed.
35+
36+
Apps without an app menu entry can't be granted this way, so users can't open them to
37+
limited app passwords from Settings yet. Files, Calendar, Contacts and Tasks have scopes
38+
of their own and can't be granted as a whole either, and neither can Assistant.
39+
40+
Opening controller methods
41+
--------------------------
42+
43+
To open single methods instead, add ``#[TokenScope]`` to a controller class or method.
44+
A limited app password can then call the method if it holds that scope:
45+
46+
.. code-block:: php
47+
48+
<?php
49+
50+
declare(strict_types=1);
51+
52+
namespace OCA\MyApp\Controller;
53+
54+
use NCU\AppFramework\Http\Attribute\TokenScope;
55+
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
56+
use OCP\AppFramework\Http\DataResponse;
57+
use OCP\AppFramework\OCSController;
58+
59+
#[TokenScope(scope: 'myapp:notes:write')]
60+
class NotesController extends OCSController {
61+
#[NoAdminRequired]
62+
#[TokenScope(scope: 'myapp:notes:read')]
63+
public function list(): DataResponse {
64+
// Needs myapp:notes:read
65+
}
66+
67+
#[NoAdminRequired]
68+
public function create(string $text): DataResponse {
69+
// Needs myapp:notes:write from the class
70+
}
71+
}
72+
73+
The attribute on a method replaces the one on its class. It doesn't add to it.
74+
75+
It's safest to put the write scope on the class and the read scope on the read
76+
methods. A method added later then needs the write scope until you decide otherwise.
77+
78+
Users can't pick your own scopes in Settings yet, only your whole app. They become useful
79+
once clients can ask for scopes themselves.
80+
81+
.. note::
82+
83+
``TokenScope`` is in the ``NCU`` namespace, so it can still change until it moves to
84+
``OCP``. See :doc:`api`.
85+
86+
Naming scopes
87+
-------------
88+
89+
Name scopes ``<appid>:<resource>:<action>``, for example ``deck:boards:read``. The
90+
action is usually ``read`` or ``write``.
91+
92+
Apps that don't ship with Nextcloud can only use scopes that start with their own app
93+
ID. A method that asks for another app's scope is refused for every limited app
94+
password, even one that holds that scope.
95+
96+
Opening DAV collections
97+
-----------------------
98+
99+
DAV collections that an app registers in its ``info.xml`` belong to that app:
100+
101+
.. code-block:: xml
102+
103+
<sabre>
104+
<collections>
105+
<collection>OCA\MyApp\Sabre\RootCollection</collection>
106+
</collections>
107+
</sabre>
108+
109+
For the example app, a limited app password needs ``myapp:dav:read`` to read them
110+
(``GET``, ``HEAD``, ``OPTIONS``, ``PROPFIND``, ``REPORT``, ``SEARCH``) and
111+
``myapp:dav:write`` for everything else, or the whole app. Users can only grant the
112+
whole app in Settings so far.
113+
114+
Built-in scopes
115+
---------------
116+
117+
These are the scopes users can pick in Settings. Apps that don't ship with Nextcloud
118+
can't ask for them, but it helps to know what an app password may hold.
119+
120+
========================================== ==============================================
121+
Scope Gives access to
122+
========================================== ==============================================
123+
``files:files:read`` Reading through the Files and Sharing APIs, previews
124+
``files:files:write`` Changing files. Without it, all files are read-only
125+
``files:dav:read``, ``files:dav:write`` Files over WebDAV
126+
``files_sharing:shares:write`` Creating and changing shares
127+
``files_trashbin:dav:read``, ``…:write`` Deleted files over WebDAV
128+
``files_versions:dav:read``, ``…:write`` File versions over WebDAV
129+
``dav:calendar:read``, ``…:write`` Calendars over CalDAV, upcoming events, calendar import and export, out of office
130+
``dav:contacts:read``, ``…:write`` Address books over CardDAV, contacts import
131+
``core:search:read`` Unified search
132+
``core:people:read`` Autocomplete, contacts menu, hovercards and profile fields
133+
``notifications:notifications:read`` Notifications and push
134+
========================================== ==============================================
135+
136+
Trying it out
137+
-------------
138+
139+
Create an app password with *Custom* access in Settings, tick your app, and call your API
140+
with it. Untick it again to check that your app refuses the app password.

‎developer_manual/digging_deeper/auth.rst‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ Users & Authentication
1111
status
1212
out_of_office
1313
oidc
14+
app_password_scopes
1415
two-factor-provider

‎developer_manual/release_notes/new.rst‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ This pages covers new features of the platform.
1111
Every feature should just have a brief description. Details have to be documented on a dedicated, persistent page.
1212
After branch-off the contents below will be cleared.
1313
14+
App password scopes
15+
-------------------
16+
17+
Users can limit an app password to some parts of their account. A limited app password
18+
can only use your app if the user grants the whole app, or if you open single controller
19+
methods with ``#[TokenScope]`` (``NCU\AppFramework\Http\Attribute\TokenScope``).
20+
See :doc:`../digging_deeper/app_password_scopes`.
21+
1422
Email template blocks
1523
---------------------
1624

0 commit comments

Comments
 (0)