# Scopes, Roles, Groups & Users: Examples needed

**URL:** <https://discourse.jupyter.org/t/scopes-roles-groups-users-examples-needed/24015>\
**Category:** JupyterHub\
**Tags:** how-to\
**Created:** [February 19, 2024, 1:33pm UTC](https://discourse.jupyter.org/t/scopes-roles-groups-users-examples-needed/24015 "2024-02-19T13:33:13Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![pgierz](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/pgierz/32/1930_2.png) [@pgierz](https://discourse.jupyter.org/u/pgierz)\
**Post date:** [February 19, 2024, 1:33pm UTC](https://discourse.jupyter.org/t/scopes-roles-groups-users-examples-needed/24015/1 "2024-02-19T13:33:13Z")

</div>

Hello together,

I have a (hopefully not too complicated) use-case which might be transformed into an example deployment, once I figure out how to actually do it.

Assume you have configured a kernel, and additionally want to offer a web-proxy-service that is available to launch if (and only if) the specified kernel is allowed to be used. I would like to be able to configure the following:

1. An admin prepares a globally available kernel with a bunch of packages. This kernel is called `Class1234_Semester02`.

2. An instructor, Professor X, username `profx`, can add and remove individual users from a group. From my understanding, this fits into the `roles`, and a set of users `instructors` can be allowed to use that `role`, ergo this is a `scope` (I think).

3. A student, Maxime Mustermann, username `mmuster` and wants to belong to a group `PythonForMorons101`. She registers for the class, the instructor gets an email, and clicks a few buttons to add the user to that group

4. When the `Spawner` launches, which happens after the authentication is complete, it notices that `mmuster` is in the group `PythonForMorons101`. When launching the actual `jupyterlab` session, it then adds an argument to it’s `cmd` which is likely something like `jupyter lab --<some cool argument>`

5. This `jupyterlab` sesssion, which is now aware of the groups of the logged in user, also offers separate web services. If the user is not in the correct group, the launcher button which creates a new tab with the web application (not a notebook), is not shown.

So, from that scenario, two questions: How do I go about implementing this? I am getting rather stuck about how all the pieces fit together. And: Once I’ve figured this out, would this be an example others are interested in, and where would I document that for the community to find?

Cheers,  
Paul

---

<div class="post-metadata">

**Author:** ![minrk](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/minrk/32/13_2.png) [@minrk](https://discourse.jupyter.org/u/minrk)\
**Post date:** [February 20, 2024, 8:57am UTC](https://discourse.jupyter.org/t/scopes-roles-groups-users-examples-needed/24015/2 "2024-02-20T08:57:54Z")

</div>

> [@pgierz](#):
>
> - An instructor, Professor X, username `profx`, can add and remove individual users from a group. From my understanding, this fits into the `roles`, and a set of users `instructors` can be allowed to use that `role`, ergo this is a `scope` (I think).

Yes, for example:

```python
c.JupyterHub.load_roles = [
    {
        "name": "instructor-group-management",
        "scopes": [
            # the 'groups' scope allows managing group membership for existing groups
            # 'admin:groups' additionally allows creating/removing groups
            "groups",
            # or only manage _specific_ groups by name:
            "groups!group=PythonForMorons101",
            "groups!group=course2",
        ],
        # members of the 'instructors' group should have this permission
        "groups": [
            "instructors",
        ],
    },
]

```

> [@pgierz](#):
>
> A student, Maxime Mustermann, username `mmuster` and wants to belong to a group `PythonForMorons101`. She registers for the class, the instructor gets an email, and clicks a few buttons to add the user to that group

Yes. One version of this is to add the `admin-ui` scope, to your instructors role, so that instructors can access the admin page, which has some UI for these actions. They will only be able to take the _actions_ they have permission for, which right now is adding and removing users from groups. They may also want the `list:users` scope. Alternately, you can deploy your own UI that makes the group management API requests with more detailed controls.

> [@pgierz](#):
>
> When the `Spawner` launches, which happens after the authentication is complete, it notices that `mmuster` is in the group `PythonForMorons101`. When launching the actual `jupyterlab` session, it then adds an argument to it’s `cmd` which is likely something like `jupyter lab --<some cool argument>`

Most spawner configuration can be modified via [spawner.pre\_spawn\_hook](https://jupyterhub.readthedocs.io/en/stable/reference/api/spawner.html#jupyterhub.spawner.Spawner.pre_spawn_hook), a hook called _immediately_ before starting the server, where you can modify all kinds of things, like `Spawner.cmd` (the executable), `Spawner.environment` (environment variables), etc.

> [@pgierz](#):
>
> This `jupyterlab` sesssion, which is now aware of the groups of the logged in user, also offers separate web services. If the user is not in the correct group, the launcher button which creates a new tab with the web application (not a notebook), is not shown.

This will depend exactly on how you make the kernel available. In many deployments, this takes the form of selecting the _image_ the user launches in, and that’s all you need to do. But that requires there being one correct choice. If you have a single big environment with lots of kernels that only some users should see, that would likely mean setting the environment variable [JUPYTER\_PATH](https://docs.jupyter.org/en/latest/use/jupyter-directories.html#data-files), and installing each [kernelspec](https://jupyter-client.readthedocs.io/en/stable/kernels.html#kernel-specs) in a different location, so you can populate the search path, which JupyterLab uses to show available kernels.
