Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send POST request to /hub/spawn/ from a service does not work in 4.1.2 #4761

Closed
trungleduc opened this issue Mar 29, 2024 · 4 comments
Closed
Labels

Comments

@trungleduc
Copy link
Contributor

Bug description

In our tljh-repo2docker service, we have a standalone UI to spawn the server by sending a POST request to the /hub/spawn/ endpoint. It works as expected up to 4.0.x.

From 4.1.2, it does not work anymore with the following error message:

[WebServer]  403 POST /hub/spawn/alice/test-server?_xsrf=MnwxOjB8...TEwODY1MmEwMmMzYQ (127.0.0.1): XSRF cookie does not match POST argument

I think it's related to #4750, since we are sending the _xsrf cookie at path /services/tljh_repo2docker/ but jupyterhub is picking the cookie at /hub/ to do the comparison.

cookies

Is there anything we can do from our side to fix this issue?

Thanks!

How to reproduce

  1. Install a dev version of tljh-repo2docker
  2. Go to http://127.0.0.1:8000/services/tljh_repo2docker/servers then start a new server

Expected behaviour

The POST request finishes without error

Actual behaviour

Your personal set up

  • OS:
  • Version(s):
    jupyterhub 4.1.2
Full environment
# paste output of `pip freeze` or `conda list` here
Configuration
# jupyterhub_config.py
Logs
@trungleduc trungleduc added the bug label Mar 29, 2024
@trungleduc
Copy link
Contributor Author

cc @jtpio

@trungleduc
Copy link
Contributor Author

We inject the xsrf_token to the page via the jinja2 template

class BaseHandler(HubOAuthenticated, web.RequestHandler):
   ...
    async def render_template(self, name: str, **kwargs) -> str:
        template_ns = dict(
            ...
            xsrf_token=self.xsrf_token.decode("ascii"),

        )
        template_ns.update(kwargs)
        template = self.get_template(name)
        return template.render(**template_ns)
   ...

https://github.com/plasmabio/tljh-repo2docker/blob/master/tljh_repo2docker/base.py#L92

@minrk
Copy link
Member

minrk commented Apr 3, 2024

Yes, this request shouldn't work, which is fixed in 4.1. Instead, the service should request permission to spawn via OAuth scopes (service.oauth_client_allowed_scopes in config, or be given permission to spawn on behalf of users without any user intervention via role assignment to the service itself) and use the resulting token to make the launch request via the API. Using tokens to authenticate requests eliminates all xsrf issues. The request can be the same originating from the browser, but put the oauth token in the Authorization header instead of the xsrf token in the URL.

c.JupyterHub.services = [
    {
        "name": "myservice",
        "oauth_client_allowed_scopes": ["servers!user"],
        ...
    }
]

@trungleduc
Copy link
Contributor Author

Thank @minrk for the pointer! We adopted the new approach and it works nicely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants