Fix broken API routes and add CSRF bypass for ExApp REST calls#132
Fix broken API routes and add CSRF bypass for ExApp REST calls#132
Conversation
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
…_agent into copilot/test-new-tools-in-pr-127
- deck.py: Fix list_boards() returning response.text instead of response.json() - mail.py: Fix wrong docstring on get_mail_account_list(), rewrite list_mail_folders, search_emails, get_email_messages, move_email_to_folder, delete_email to use correct Nextcloud Mail REST API routes instead of nonexistent OCS routes - polls.py: Fix all routes to include correct /api/v1.0/ prefix, fix create_poll payload (API doesn't accept description), fix add_poll_option payload structure, fix vote_on_poll to use correct URL-based answer format - forms.py: Update from nonexistent v2.4 API to correct v3 API, fix create_form to use two-step create+update pattern, fix add_question_to_form payload, fix option creation to use batch optionTexts parameter - files.py: Fix get_folder_tree to use params= instead of json= for GET request Co-authored-by: marcelklehr <986878+marcelklehr@users.noreply.github.com>
|
@copilot Make sure that the APIs we use do not requre the sending of CSRF tokens, as we don't have those in an ex app context |
Nextcloud's SecurityMiddleware enforces CSRF checks on controller methods without @NoCSRFRequired. ExApps don't have CSRF tokens, but Nextcloud's Request::passesCSRFCheck() bypasses CSRF if the OCS-APIREQUEST header is present (any non-empty value). The nc_py_api library sets this header on the main OCS adapter, but NOT on fresh adapters created via _create_adapter(True) used for REST calls. Added "OCS-APIREQUEST": "true" header to all non-DAV REST API calls in: bookmarks, cookbook, deck, mail, music, news, passwords, photos. DAV calls (files.py, contacts.py, calendar.py) use /remote.php/dav/ which goes through Sabre auth (AppAPIAuthBackend), not the CSRF middleware. OCS calls (forms.py, polls.py, notes.py, circles.py, shares.py) already have CSRF bypass via the OCS adapter's built-in OCS-APIREQUEST header. Co-authored-by: marcelklehr <986878+marcelklehr@users.noreply.github.com>
Audited all API routes for CSRF requirements. The issue: The fix in faac2a1: added Routes that don't need this fix:
|
Audited all new tool modules from PR #127 against upstream Nextcloud app source code. Found 5 tools with incorrect API routes or payloads that would fail at runtime, and identified a CSRF token issue affecting all non-DAV REST API calls from ExApp context.
deck.py
list_boards()returnedresponse.textinstead ofresponse.json()mail.py
get_mail_account_list()had copy-pasted docstring fromsend_emaillist_mail_folders,search_emails,get_email_messages,move_email_to_folder,delete_emailall used nonexistent OCS routes — the Mail app exposes these as REST endpoints at/index.php/apps/mail/api/, not OCSpolls.py
/api/v1.0/prefix (e.g./ocs/v2.php/apps/polls/polls→/ocs/v2.php/apps/polls/api/v1.0/polls)create_pollpasseddescriptionparam the API doesn't acceptadd_poll_optionused wrong payload key (pollOptionText→optionarray)vote_on_pollpassed answer in JSON body; API expects it in URL path (/option/{id}/vote/{answer})forms.py
create_formpassedtitle/descriptiontonewFormwhich only acceptsfromId— now uses two-step create + PATCHadd_question_to_formused wrong routes and option creation used per-item POST instead of batchoptionTextsupdate_form_settingsused wrong route and payload format (needskeyValuePairswrapper)files.py
get_folder_tree()passeddepthviajson=(request body) on a GET request; changed toparams=CSRF bypass for ExApp REST calls
Nextcloud's
SecurityMiddlewareenforces CSRF checks on controller methods without@NoCSRFRequired. ExApps don't have CSRF tokens, butRequest::passesCSRFCheck()bypasses CSRF when theOCS-APIREQUESTheader is present. Thenc_py_apilibrary sets this header on the main OCS adapter, but NOT on fresh adapters created via_create_adapter(True)used for REST calls.Added
"OCS-APIREQUEST": "true"to all non-DAV REST API calls in: bookmarks, cookbook, deck, mail, music, news, passwords, photos.Routes that don't need this fix:
nc.ocs()adapter already setsOCS-APIREQUEST: true/remote.php/dav/with Sabre auth (AppAPIAuthBackend), not the CSRF middlewareVerified correct (no changes needed beyond CSRF header)
bookmarks, circles, cookbook, music, news, notes, passwords, photos, shares
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.