Skip to content

Commit

Permalink
Investigate the xsrf token issue (#27)
Browse files Browse the repository at this point in the history
* Add test for xsrf not being require in jupyter-server

* Pass xsrf token explicitly in the `/pull` POST request

* Add xsrf token in the event source too
  • Loading branch information
krassowski authored Jun 28, 2024
1 parent 63b55cb commit dd9d71c
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 3 deletions.
7 changes: 6 additions & 1 deletion jupyterlab_gallery/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,12 @@ class PullHandler(BaseHandler, SyncHandlerBase):
async def post(self):
data = self.get_json_body()
exhibit_id = data["exhibit_id"]
exhibit = self.gallery_manager.exhibits[exhibit_id]
try:
exhibit = self.gallery_manager.exhibits[exhibit_id]
except IndexError:
self.set_status(406)
self.finish(json.dumps({"message": f"exhibit_id {exhibit_id} not found"}))
return
return await super()._pull(
repo=exhibit["git"],
exhibit_id=exhibit_id,
Expand Down
19 changes: 19 additions & 0 deletions jupyterlab_gallery/tests/test_handlers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import json

from jupyter_server.utils import url_path_join


async def test_exhibits(jp_fetch):
response = await jp_fetch("jupyterlab-gallery", "exhibits")
Expand All @@ -13,3 +15,20 @@ async def test_gallery(jp_fetch):
assert response.code == 200
payload = json.loads(response.body)
assert payload["apiVersion"] == "1.0"


async def test_pull_token_can_be_used_instead_of_xsrf(jp_serverapp, jp_base_url, http_server_client):
token = jp_serverapp.identity_provider.token
response = await http_server_client.fetch(
url_path_join(jp_base_url, "jupyterlab-gallery", "pull"),
body=b'{"exhibit_id": 100}',
method="POST",
headers={
"Authorization": f"token {token}",
"Cookie": ""
},
raise_error=False,
)
assert response.code == 406
payload = json.loads(response.body)
assert payload["message"] == "exhibit_id 100 not found"
9 changes: 8 additions & 1 deletion src/gallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,16 @@ export class GalleryWidget extends ReactWidget {
};
this._stream.connect(promiseResolver);
});
const xsrfTokenMatch = document.cookie.match('\\b_xsrf=([^;]*)\\b');
const args: Record<string, string | number> = {
exhibit_id: exhibit.id
};
if (xsrfTokenMatch) {
args['_xsrf'] = xsrfTokenMatch[1];
}
await requestAPI('pull', {
method: 'POST',
body: JSON.stringify({ exhibit_id: exhibit.id })
body: JSON.stringify(args)
});
await done;
}
Expand Down
8 changes: 7 additions & 1 deletion src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,17 @@ export function eventStream(
onError: (error: Event) => void
): EventSource {
const settings = ServerConnection.makeSettings();
const requestUrl = URLExt.join(
let requestUrl = URLExt.join(
settings.baseUrl,
'jupyterlab-gallery', // API Namespace
endPoint
);
const xsrfTokenMatch = document.cookie.match('\\b_xsrf=([^;]*)\\b');
if (xsrfTokenMatch) {
const fullUrl = new URL(requestUrl);
fullUrl.searchParams.append('_xsrf', xsrfTokenMatch[1]);
requestUrl = fullUrl.toString();
}
const eventSource = new EventSource(requestUrl);
eventSource.addEventListener('message', event => {
const data = JSON.parse(event.data);
Expand Down

0 comments on commit dd9d71c

Please sign in to comment.