Authenticators#
Users and roles#
Grader Service authorizes actions through per-lecture roles. A role links a user to a lecture with a scope. The scope is the Scope enum (grader_service.orm.takepart.Scope):
Value |
Scope |
|---|---|
0 |
|
1 |
|
2 |
|
3 |
|
Grader Service does not ship a dedicated admin command for creating users or assigning roles. Users and roles are populated from the configured authenticator instead, in one or both of these ways:
post_auth_hook: the authenticator’s post-authentication hook receives the authenticated user’s groups and interprets any group of the formlecture_code:scope(for exampleintro:instructor) as a role assignment, creating the lecture and the role if they do not yet exist and updating the role otherwise. This is how group-based identity providers (e.g. an LMS or institutional IdP) drive enrollment. Because the hook looks up the scope by name, anyScopevalue (student,tutor,instructor,admin) can be assigned this way.c.GraderService.load_roles: a static mapping of lecture code to role definitions that is loaded into the database at service startup. Each role definition lists itsmembers(usernames or user dicts) and therole(student,tutororinstructor).
A reference implementation of both mechanisms, including a full post_auth_hook, is in the development configuration at dev/local/token/grader_service_config.py. Use it as a template for your own deployment config.
DummyAuthenticator#
from grader_service.auth.dummy import DummyAuthenticator
c.GraderService.authenticator_class = DummyAuthenticator
c.DummyAuthenticator.password = 'test'
# c.Authenticator.allowed_users = {'admin1', 'admin2', 'instructor', 'tutor', 'student1', 'student2'}
c.Authenticator.allow_all = True
# c.Authenticator.admin_users = {'admin1', 'admin2'}
PAMAuthenticator#
Uses PAM-based authentication to log in local system users.
from grader_service.auth.pam import PAMAuthenticator
c.GraderService.authenticator_class = PAMAuthenticator
OAuthenticator#
Example configuration for grader_service_config.py using Google OAuth.
from grader_service.auth.oauth2 import OAuthenticator
c.GraderService.authenticator_class = OAuthenticator
c.OAuthenticator.client_id = "<client_id>"
c.OAuthenticator.client_secret = "<client_secret>"
c.OAuthenticator.authorize_url = "https://accounts.google.com/o/oauth2/auth"
c.OAuthenticator.token_url = "https://oauth2.googleapis.com/token"
c.OAuthenticator.scope = ['email']
c.OAuthenticator.userdata_url = "https://www.googleapis.com/oauth2/v1/userinfo"
c.OAuthenticator.username_claim = "email"
# c.OAuthenticator.admin_users = {'admin1', 'admin2'}
LTI 1.3 Authenticator#
Log in using the LTI authentication flow. This example configuration is based on a local Moodle setup based on moodle-docker.
c.LTI13Authenticator.issuer = "http://localhost:8000"
c.LTI13Authenticator.authorize_url = "http://localhost:8000/mod/lti/auth.php"
# The platform's JWKS endpoint url providing public key sets used to verify the ID token
c.LTI13Authenticator.jwks_endpoint = "http://localhost:8000/mod/lti/certs.php"
# The external tool's client id as represented within the platform (LMS)
c.LTI13Authenticator.client_id = ["<client_id>"] # generated by Moodle etc. after creating external tool
In Moodle itself the external tool configuration is as follows, given that the Grader Service runs on localhost:4010 and JupyterHub runs on localhost:8080.
Tool URL:
http://localhost:4010/?next=http%3A%2F%2Flocalhost%3A8080
This becomes the target_link_uri of the login request. If this contains a next URL query parameter, it is extracted and used by the Grader Service to redirect after the authentication flow.
In this case we redirect to http://localhost:8080, which is the JupyterHub.
LTI version:
LTI 1.3
Public key type:
Keyset URL
The Public keyset field can be left empty.
Initiate login URL:
http://localhost:4010/services/grader/lti13/oauth_login
The login handler of the Grader Service.
Redirection URI(s):
http://localhost:4010/services/grader/lti13/oauth_callback
The callback handler for the OAuth flow.
Configuration for JupyterHub#
After authentication is complete the Grader Service will redirect to the JupyterHub (as specified in the Tool URL), from which the user is authenticated via OAuth.
JupyterHub now uses the Grader Service as an IDP using its OAuthenticator implementation.
from oauthenticator.generic import GenericOAuthenticator
c.JupyterHub.authenticator_class = GenericOAuthenticator
c.GenericOAuthenticator.oauth_callback_url = "http://localhost:8080/hub/oauth_callback"
c.GenericOAuthenticator.client_id = "hub"
c.GenericOAuthenticator.client_secret = "hub"
c.GenericOAuthenticator.authorize_url = "http://localhost:4010/services/grader/api/oauth2/authorize"
c.GenericOAuthenticator.token_url = "http://localhost:4010/services/grader/api/oauth2/token"
c.GenericOAuthenticator.userdata_url = "http://localhost:4010/services/grader/api/user"
c.GenericOAuthenticator.username_claim = "name"
In the Grader Service config the JupyterHub has to be registered as a client.
c.GraderService.oauth_clients = [{
'client_id': 'hub',
'client_secret': 'hub',
'redirect_uri': 'http://localhost:8080/hub/oauth_callback'
}]