JupyterHub and Moodle integration

@jnaranjo104 Re: integrating with Moodle, how tight an integration are you looking at? One weakly coupled way is to provide an LTI authed link in a Moodle page that is handled by a Jupyterhub client. eg https://github.com/jupyterhub/ltiauthenticator/blob/master/README.md#moodle

Moved this to its own thread so that “Introduce yourself” remains discussion free.

Thanks a lot for your answer Tony. I had a look at that link as I mention in the post LTi authenticator setup
But when I include:
c.JupyterHub.authenticator_class = ‘ltiauthenticator.LTIAuthenticator’

c.LTIAuthenticator.consumers = {
“client-key”: “client-secret”
In my jupyterhub_config.py file, the service does not start and I get an error related to the ltiauthenticator class. It seems I have to add some other lines in that file like:

from ltiauthenticator import LTIAuthenticator

In the same way as for instance:
from jupyterhub.auth import LocalAuthenticator

Is included for Local Autentication

But if I include “from ltiauthenticator import LTIAuthenticator” in the jupyterhub_config.py file the server does not start and a new error is shown: ltiauthenticator can not be loaded, etc.

I hope you can help me to identify how should I call ltiauthenticator library in the configuration file.

Thanks in advance

Hi again: Doing further investigation I have seen that at installation, “ltiauthenticator” and “jupyterhub_ltiauthenticator” are under “/usr/local…” and the other libraries for JupyterHub are under “/opt/tljh…”. If I copy files from “/usr/local…” to “/opt/tljh/…” the service starts properly, though I get a new error: “405: Method not allowed” when trying to “http://ip/hub/lti/launch”. I think that I have to configure an additional authentication method to keep the option to connect to the administration URL for JupyterHub directly or even in the case that people from the department would like to connect to JupyterHub away from Moodle, etc.
I’ll keep you posted of any progress I get on this.

Best regards

Hi everybody interested in this topic: Once the issue related to the location of files mentioned above was fixed, I followed the instructions mentioned at https://github.com/jupyterhub/ltiauthenticator/blob/master/README.md#moodle, and also at: https://docs.moodle.org/37/en/External_tool_settings. What I can tell you is that it works. I have created in Moodle an External Tool and assigned it to a course I had previously created too. The access to JupyterHub (TLJH in my case) from Moodle works.
What I have seen is that from the OS perspective, only a user account is created at first connection from Moodle course without regards if I launch the external tool with a Moodle user or with other.
With all of this in mind, next steps are:

  1. Configure additional authentication methods in JupyterHub so that I can log into the tools directly in addition to be able to log from Moodle.
  2. Further investigation to get a OS User for every Moodle user that launch the External Tool so they can have independent environments.

If anybody can provide any starting point for every one of the steps mentioned above, will be welcome.

Best regards,



Jupyterhub uses python virtualenv to contain all it’s python libraries. You would need to use the pip that was installed in the virtualenv, /opt/tljh/hub/bin/pip, to have the libraries installed for them to be available to jupyterhub. If you specify the moodle user id in the admin section of the config, those users should see the admin control panel etc, when they use the lti authenticated link from moodle. Good to see you have it now working in your follow up post.



Hi Rod: Thanks a lot for your answer. I guess you are referring to the following ticks:

As you can see I have already marked them but when I launch the external tool from Moodle, what I get is:

And the user name is “3”.

I’d appreciate if you can provide additional feedback.

Best regards,



you would need to edit config.yaml so that it has the entry:

  - '3'

I tried using tljh-config add-item users.admin ‘3’’ but it will add the number 3 not the quote value that is required, otherwise it will fail to compare the int to the string of the username…

Once you have restarted tljh and reloaded the browseryou should hopefully see the admin button…



1 Like

Thanks a lot Rod for your answer. I’ll try and will let you know.

Another problem I am having is that when I try to connect directly to TLJH through the web browser instead of by means of Moodle external tool, the connection is refused as it seems that the only authentication method available is LTI.

Have you any idea if I can keep PAM or LocalAutehntication in addition to LTI Authentication: PAM for local users and LTI for Moodle users? Should I configure different URL’s for every service?

LTI can be reached at “http://localIP/hub/lti/launch
Which should it be the Local or PAM Autehntication URL?

If I try “http://localIP/hub/login” it redirects to “http://localIP/hub/lti/launch” and a 405 error is shown.

Thanks in advance for your support.

Best regards,


1 Like

I think this is due to the LTIAuthenticaton being configured to Auto Login,
But if you set the LTIAuthentication to not AutoLogin, you get a login with LTI button if you go to hub/login

Not sure how the multiple authentications are handled if they are define.

Maybe you have to define a combined auth class, like the last few lines in :

I haven’t been able to find any documentation to describe how this works or needs to be configured,



Hi Rod: Thanks a lot for your answer on this. I have seen something similar in other examples like in https://github.com/jupyterhub/oauthenticator/blob/fdd2d5b16db616774cd18a589f6d7f35d6eb2c32/oauthenticator/github.py or in https://github.com/jupyterhub/oauthenticator/blob/fdd2d5b16db616774cd18a589f6d7f35d6eb2c32/oauthenticator/auth0.py
I’ll have a look at the init.py file under LTIAuthenticator directory in order to see if those lines are included and will try.

I’ll let you know if I success.

Best regards,


Hi Rob: I have been doing some additional tries on this matter (having more than one authentication method activated) but unfortunately, I have been unable to progress.
I’ll come back to this issue later in my job anyway.
Thanks a lot for your support Rob.
Regarding COVID19, I hope you all are well and little affected.


Dear Jose and all,

I have a working JupyterHub installation and now I am also trying to use JupyterHub with Moodle. Unfortunately now I am stuck with the 405 “Method not allowed” error, which I get when I try to access jupyterhub from the Moodle activity.

I have added the following lines in my jupyterhub_config.py file:

from ltiauthenticator import LTIAuthenticator

c.JupyterHub.authenticator_class = 'ltiauthenticator.LTIAuthenticator'

c.LTIAuthenticator.consumers = {
       "abcdefghijklmnop1234567890.....": "secretxyz01234567890....."

In Moodle I created the external tool:

jupyterhub-ltiauthenticator is installed in the correct path of the virtual environment for jupyterhub and everything runs over HTTPS.

I have tried and tried, but no more ideas what could be going wrong. Can anyone help?

Thanks a lot in advance!

You can check https://github.com/IllumiDesk/illumidesk we just released jupyterhub authenticators for LTI 1.1 and 1.3 versions (tested with canvas/moodle). Feel free to review and give us your feedback

Hi netoisc,

thanks a lot for your reply!

Your setup looks great, but is currently an overkill for me - I only need the login part from Moodle into JupyterHub.

I tried the jupyterhub/ltiauthenticator, should that work with LTI 1.1?

If not, and if I want to use only your authenticator, what would be the steps to do? My guess for LTI 1.1:

  • Make sure the file authenticators.py is available
  • add this to my jupyterhub_config.py:
    from illumidesk.authenticators.authenticator import LTI11Authenticator
    c.JupyterHub.authenticator_class = LTI11Authenticator
  • Configure the keys somewhere - but I don’t see where

Thanks for your help!

Hi @netoisc
I’m trying to integrate Jupyterhub with canvas what you did as illumidesk. Please give the instructions, how to integrate it with canvas.

Is this what you’re looking for?

--- ltiauthenticator/__init__.py.orig   2021-08-01 11:35:32.047430657 +0900
+++ ltiauthenticator/__init__.py    2021-08-01 11:45:27.120452288 +0900
@@ -157,9 +157,13 @@
             # If Canvas is running in anonymous mode, we'll still want the 'user_id' (which is the `lti_user_id``)

             canvas_id = handler.get_body_argument('custom_canvas_user_id', default=None)
+            # by T.ISHIZAKA, Y.KUWATA, et. al., Moodle Moot Japan 2019 Proceedings (2019), pp.32-37
+            product_code = handler.get_body_argument('tool_consumer_info_product_family_code', default=None)

             if canvas_id is not None:
                 user_id = handler.get_body_argument('custom_canvas_user_id')
+            elif 'moodle' in product_code:
+                user_id = handler.get_body_argument('ext_user_username')
                 user_id = handler.get_body_argument('user_id')


ltiauthenticator v1.2.0 is released

v1.2.0 does not need patch for Moodle.

My configuration is

# for LTI v1.2.0
c.JupyterHub.authenticator_class = 'ltiauthenticator.LTIAuthenticator'

c.LTI11Authenticator.consumers = {
    "b18e82ec683724743236fade71350720029a29144a585c66f6741d8e9c6e0d83" : "c0fe2924dbb0f4701d898d36aaf9fd89c7a3ed3a7db6f0003d0e825a7eccb41c"
c.LTI11Authenticator.username_key = 'ext_user_username'



We are currently researching the use of LTI to integration of Moodle and JupyterHub.
In this work, we use LTI custom parameters from Moodle to control the JupyterHub and the Jupyter containers.

If you are interested, please visit the following URL