openedx.core.djangoapps.user_authn.views package#
Submodules#
openedx.core.djangoapps.user_authn.views.auth module#
Views related to auth.
- openedx.core.djangoapps.user_authn.views.auth.get_public_signing_jwks(request)#
View to provide the auth related public signing JWK set as json.
openedx.core.djangoapps.user_authn.views.auto_auth module#
Views related to auto auth.
- openedx.core.djangoapps.user_authn.views.auto_auth.auto_auth(request)#
Create or configure a user account, then log in as that user.
Enabled only when settings.FEATURES[‘AUTOMATIC_AUTH_FOR_TESTING’] is true.
Accepts the following querystring parameters: * username, email, and password for the user account * full_name for the user profile (the user’s full name; defaults to the username) * staff: Set to “true” to make the user global staff. * course_id: Enroll the student in the course with course_id * roles: Comma-separated list of roles to grant the student in the course with course_id * no_login: Define this to create the user but not login * redirect: Set to “true” will redirect to the redirect_to value if set, or
course home page if course_id is defined, otherwise it will redirect to dashboard
redirect_to: will redirect to to this url
is_active : make/update account with status provided as ‘is_active’
should_manually_verify: Whether the created user should have their identification verified
If username, email, or password are not provided, use randomly generated credentials.
openedx.core.djangoapps.user_authn.views.login module#
Views for login / logout and associated functionality
Much of this file was broken out from views.py, previous history can be found there.
- class openedx.core.djangoapps.user_authn.views.login.LoginSessionView(**kwargs)#
Bases:
APIViewHTTP end-points for logging in users.
- authentication_classes = []#
- dispatch(request, *args, **kwargs)#
.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.
- get(request, *args, **kwargs)#
- login_user_responses = {200: {'properties': {'error_code': {'type': 'string'}, 'success': {'type': 'boolean'}, 'value': {'type': 'string'}}, 'type': 'object'}, 400: {'properties': {'error_code': {'type': 'string'}, 'success': {'type': 'boolean'}, 'value': {'type': 'string'}}, 'type': 'object'}, 403: {'properties': {'error_code': {'type': 'string'}, 'success': {'type': 'boolean'}, 'value': {'type': 'string'}}, 'type': 'object'}}#
- post(request, api_version)#
POST /user/{api_version}/account/login_session/
Returns 200 on success, and a detailed error message otherwise.
- openedx.core.djangoapps.user_authn.views.login.enterprise_selection_page(request, user, next_url)#
Updates redirect url to enterprise selection page if user is associated with multiple enterprises otherwise return the next url.
- param:
next_url(string): The URL to redirect to after multiple enterprise selection or in case the selection page is bypassed e.g when dealing with direct enrolment urls.
- openedx.core.djangoapps.user_authn.views.login.finish_auth(request)#
Following logistration (1st or 3rd party), handle any special query string params.
See FinishAuthView.js for details on the query string params.
e.g. auto-enroll the user in a course, set email opt-in preference.
This view just displays a “Please wait” message while AJAX calls are made to enroll the user in the course etc. This view is only used if a parameter like “course_id” is present during login/registration/third_party_auth. Otherwise, there is no need for it.
Ideally this view will finish and redirect to the next step before the user even sees it.
- Parameters:
request (HttpRequest)
- Returns:
200 if the page was sent successfully HttpResponse: 302 if not logged in (redirect to login page) HttpResponse: 405 if using an unsupported HTTP method
- Return type:
HttpResponse
Example usage:
GET /account/finish_auth/?course_id=course-v1:blah&enrollment_action=enroll
- openedx.core.djangoapps.user_authn.views.login.login_refresh(request)#
- openedx.core.djangoapps.user_authn.views.login.login_user(request, api_version='v1')#
AJAX request to log in the user.
- Parameters:
request (HttpRequest)
- Required params:
email, password
- Optional params:
- analytics: a JSON-encoded object with additional info to include in the login analytics event. The only
supported field is “enroll_course_id” to indicate that the user logged in while enrolling in a particular course.
- Returns:
- 200 if successful.
Ex. {‘success’: true}
- HttpResponse: 400 if the request failed.
Ex. {‘success’: false, ‘value’: ‘{‘success’: false, ‘value: ‘Email or password is incorrect.’}
- HttpResponse: 403 if successful authentication with a third party provider but does not have a linked account.
Ex. {‘success’: false, ‘error_code’: ‘third-party-auth-with-no-linked-account’}
- Return type:
HttpResponse
Example Usage:
POST /login_ajax with POST params email, password
200 {‘success’: true}
- openedx.core.djangoapps.user_authn.views.login.redirect_to_lms_login(request)#
This view redirect the admin/login url to the site’s login page if waffle switch is on otherwise returns the admin site’s login view.
openedx.core.djangoapps.user_authn.views.login_form module#
Login related views
- openedx.core.djangoapps.user_authn.views.login_form.get_login_session_form(request)#
Return a description of the login form.
This decouples clients from the API definition: if the API decides to modify the form, clients won’t need to be updated.
See user_api.helpers.FormDescription for examples of the JSON-encoded form description.
- Returns:
HttpResponse
- openedx.core.djangoapps.user_authn.views.login_form.login_and_registration_form(request, initial_mode='login')#
Render the combined login/registration form, defaulting to login
This relies on the JS to asynchronously load the actual form from the user_api.
- Keyword Arguments:
initial_mode (string) – Either “login” or “register”.
openedx.core.djangoapps.user_authn.views.logout module#
Views related to logout.
- class openedx.core.djangoapps.user_authn.views.logout.LogoutView(**kwargs)#
Bases:
TemplateViewLogs out user and redirects.
The template should load iframes to log the user out of OpenID Connect services. See http://openid.net/specs/openid-connect-logout-1_0.html.
- default_target = '/'#
- dispatch(request, *args, **kwargs)#
- get_context_data(**kwargs)#
- oauth_client_ids = []#
- post(request, *args, **kwargs)#
Proxy to the GET handler.
TODO: remove GET as an allowed method, and update all callers to use POST.
- property target#
If a redirect_url is specified in the querystring for this request, and the value is a safe url for redirect, the view will redirect to this page after rendering the template. If it is not specified, we will use the default target url. Redirect to tpa_logout_url if TPA_AUTOMATIC_LOGOUT_ENABLED is set to True and if tpa_logout_url is configured.
- template_name = 'logout.html'#
- tpa_logout_url = ''#
openedx.core.djangoapps.user_authn.views.password_reset module#
Password reset logic and views .
- class openedx.core.djangoapps.user_authn.views.password_reset.LogistrationPasswordResetView(**kwargs)#
Bases:
APIViewAPI to update new password credentials for a correct token
- post(request, **kwargs)#
Reset learner password using passed token and new credentials
- throttle_classes = [<class 'openedx.core.djangoapps.user_authn.views.password_reset.PasswordResetThrottle'>]#
- class openedx.core.djangoapps.user_authn.views.password_reset.PasswordResetConfirmWrapper#
Bases:
PasswordResetConfirmView- A wrapper around django.contrib.auth.views.PasswordResetConfirmView.
Needed because we want to set the user as active at this step. We also optionally do some additional password policy checks.
- dispatch(*args, **kwargs)#
- post(request, *args, **kwargs)#
Handle POST requests: instantiate a form instance with the passed POST variables and then check if it’s valid.
- class openedx.core.djangoapps.user_authn.views.password_reset.PasswordResetFormNoActive(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None, bound_field_class=None)#
Bases:
PasswordResetFormA modified version of the default Django password reset form to handle unknown or unusable email addresses without leaking data.
- base_fields = {'email': <django.forms.fields.EmailField object>}#
- clean_email()#
This is a literal copy from Django 1.4.5’s django.contrib.auth.forms.PasswordResetForm Except removing the requirement of active users Validates that a user exists with the given email address.
- declared_fields = {'email': <django.forms.fields.EmailField object>}#
- error_messages = {'unknown': "That e-mail address doesn't have an associated user account. Are you sure you've registered?", 'unusable': 'The user account associated with this e-mail address cannot reset the password.'}#
- is_account_recovery = True#
- property media#
Return all media required to render the widgets on this form.
- save(use_https=False, token_generator=<django.contrib.auth.tokens.PasswordResetTokenGenerator object>, request=None, **_kwargs)#
Generates a one-use only link for resetting password and sends to the user.
- users_cache = []#
- class openedx.core.djangoapps.user_authn.views.password_reset.PasswordResetThrottle#
Bases:
AnonRateThrottleSetting rate limit for password reset
- parse_rate(rate)#
Given the request rate string, return a two tuple of: <allowed number of requests>, <period of time in seconds>
- rate = '30/7d'#
- class openedx.core.djangoapps.user_authn.views.password_reset.PasswordResetTokenValidation(**kwargs)#
Bases:
APIViewAPI to validate generated password reset token
- post(request)#
HTTP end-point to validate password reset token.
- throttle_classes = [<class 'openedx.core.djangoapps.user_authn.views.password_reset.ResetTokenValidationThrottle'>]#
- class openedx.core.djangoapps.user_authn.views.password_reset.PasswordResetView(**kwargs)#
Bases:
APIViewHTTP end-point for GETting a description of the password reset form.
- authentication_classes = []#
- get(request)#
- class openedx.core.djangoapps.user_authn.views.password_reset.ResetTokenValidationThrottle#
Bases:
AnonRateThrottleSetting rate limit for token validation
- parse_rate(rate)#
Given the request rate string, return a two tuple of: <allowed number of requests>, <period of time in seconds>
- rate = '30/7d'#
- openedx.core.djangoapps.user_authn.views.password_reset.get_password_reset_form()#
Return a description of the password reset form.
This decouples clients from the API definition: if the API decides to modify the form, clients won’t need to be updated.
See user_api.helpers.FormDescription for examples of the JSON-encoded form description.
- Returns:
HttpResponse
- openedx.core.djangoapps.user_authn.views.password_reset.get_user_default_email_params(user)#
Get default email params for the user.
- openedx.core.djangoapps.user_authn.views.password_reset.password_change_request_handler(request)#
Handle password change requests originating from the account page.
Uses the Account API to email the user a link to the password reset page.
Note
The next step in the password reset process (confirmation) is currently handled by student.views.password_reset_confirm_wrapper, a custom wrapper around Django’s password reset confirmation view.
- Parameters:
request (HttpRequest)
- Returns:
200 if the email was sent successfully HttpResponse: 400 if there is no ‘email’ POST parameter HttpResponse: 403 if the client has been rate limited HttpResponse: 405 if using an unsupported HTTP method
- Return type:
HttpResponse
Example usage:
POST /account/password
- openedx.core.djangoapps.user_authn.views.password_reset.password_reset(request)#
Attempts to send a password reset e-mail.
- openedx.core.djangoapps.user_authn.views.password_reset.request_password_change(email, is_secure)#
Email a single-use link for performing a password reset.
Users must confirm the password change before we update their information.
- Parameters:
email (str) – An email address
orig_host (str) – An originating host, extracted from a request with get_host
is_secure (bool) – Whether the request was made with HTTPS
- Returns:
None
- Raises:
errors.UserAPIInternalError – the operation failed due to an unexpected error.
- openedx.core.djangoapps.user_authn.views.password_reset.send_password_reset_email_for_user(user, request, preferred_email=None)#
Send out a password reset email for the given user.
- Parameters:
user (User) – Django User object
request (HttpRequest) – Django request object
preferred_email (str) – Send email to this address if present, otherwise fallback to user’s email address.
openedx.core.djangoapps.user_authn.views.register module#
Registration related views.
- class openedx.core.djangoapps.user_authn.views.register.RegistrationValidationView(**kwargs)#
Bases:
APIViewUse Cases
Get validation information about user data during registration. Client-side may request validation for any number of form fields, and the API will return a conclusion from its analysis for each input (i.e. valid or not valid, or a custom, detailed message).
Example Requests and Responses
Checks the validity of the username and email inputs separately.
POST /api/user/v1/validation/registration/ >>> { >>> “username”: “hi_im_new”, >>> “email”: “newguy101@edx.org” >>> } RESPONSE >>> { >>> “validation_decisions”: { >>> “username”: “”, >>> “email”: “” >>> } >>> } Empty strings indicate that there was no problem with the input.
Checks the validity of the password field (its validity depends upon both the username and password fields, so we need both). If only password is input, we don’t check for password/username compatibility issues.
POST /api/user/v1/validation/registration/ >>> { >>> “username”: “myname”, >>> “password”: “myname” >>> } RESPONSE >>> { >>> “validation_decisions”: { >>> “username”: “”, >>> “password”: “Password cannot be the same as the username.” >>> } >>> }
Checks the validity of the username, email, and password fields separately, and also tells whether an account exists. The password field’s validity depends upon both the username and password, and the account’s existence depends upon both the username and email.
POST /api/user/v1/validation/registration/ >>> { >>> “username”: “hi_im_new”, >>> “email”: “cto@edx.org”, >>> “password”: “p” >>> } RESPONSE >>> { >>> “validation_decisions”: { >>> “username”: “”, >>> “email”: “It looks like cto@edx.org belongs to an existing account. Try again with a different email address.”, >>> “password”: “Password must be at least 2 characters long”, >>> } >>> } In this example, username is valid and (we assume) there is a preexisting account with that email. The password also seems to contain the username.
Note that a validation decision is returned for all inputs, whether positive or negative.
Available Handlers
- “name”:
A handler to check the validity of the user’s real name.
- “username”:
A handler to check the validity of usernames.
- “email”:
A handler to check the validity of emails.
- “confirm_email”:
A handler to check whether the confirmation email field matches the email field.
- “password”:
A handler to check the validity of passwords; a compatibility decision with the username is made if it exists in the input.
- “country”:
A handler to check whether the validity of country fields.
- authentication_classes = []#
- confirm_email_handler(request)#
Confirm email validator
- country_handler(request)#
Country validator
- email_handler(request)#
Validates whether the email address is valid.
- name_handler(request)#
Validates whether fullname is valid
- password_handler(request)#
Password validator
- post(request)#
POST /api/user/v1/validation/registration/
Expects request of the form ``` {
“name”: “Dan the Validator”, “username”: “mslm”, “email”: “mslm@gmail.com”, “confirm_email”: “mslm@gmail.com”, “password”: “password123”, “country”: “PK”
}#
where each key is the appropriate form field name and the value is user input. One may enter individual inputs if needed. Some inputs can get extra verification checks if entered along with others, like when the password may not equal the username.
- username_handler(request)#
Validates whether the username is valid.
- username_suggestions = []#
- validation_handlers = {'confirm_email': <function RegistrationValidationView.confirm_email_handler>, 'country': <function RegistrationValidationView.country_handler>, 'email': <function RegistrationValidationView.email_handler>, 'name': <function RegistrationValidationView.name_handler>, 'password': <function RegistrationValidationView.password_handler>, 'username': <function RegistrationValidationView.username_handler>}#
- class openedx.core.djangoapps.user_authn.views.register.RegistrationView(**kwargs)#
Bases:
APIViewHTTP end-points for creating a new user.
- authentication_classes = []#
- dispatch(request, *args, **kwargs)#
.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.
- get(request)#
- post(request)#
Create the user’s account.
You must send all required form fields with the request.
You can optionally send a “course_id” param to indicate in analytics events that the user registered while enrolling in a particular course.
- Parameters:
request (HTTPRequest)
- Returns:
200 on success HttpResponse: 400 if the request is not valid. HttpResponse: 409 if an account with the given username or email
address already exists
HttpResponse: 403 operation not allowed
- Return type:
HttpResponse
- openedx.core.djangoapps.user_authn.views.register.create_account_with_params(request, params)#
Given a request and a dict of parameters (which may or may not have come from the request), create an account for the requesting user, including creating a comments service user object and sending an activation email. This also takes external/third-party auth into account, updates that as necessary, and authenticates the user for the request’s session.
Does not return anything.
Raises AccountValidationError if an account with the username or email specified by params already exists, or ValidationError if any of the given parameters is invalid for any other reason.
Issues with this code: * It is non-transactional except where explicitly wrapped in atomic to
alleviate deadlocks and improve performance. This means failures at different places in registration can leave users in inconsistent states.
Third-party auth passwords are not verified. There is a comment that they are unused, but it would be helpful to have a sanity check that they are sane.
The user-facing text is rather unfriendly (e.g. “Username must be a minimum of two characters long” rather than “Please use a username of at least two characters”).
Duplicate email raises a ValidationError (rather than the expected AccountValidationError). Duplicate username returns an inconsistent user message (i.e. “An account with the Public Username ‘{username}’ already exists.” rather than “It looks like {username} belongs to an existing account. Try again with a different username.”) The two checks occur at different places in the code; as a result, registering with both a duplicate username and email raises only a ValidationError for email only.
- openedx.core.djangoapps.user_authn.views.register.is_new_user(password, user)#
openedx.core.djangoapps.user_authn.views.registration_form module#
Objects and utilities used to construct registration forms.
- class openedx.core.djangoapps.user_authn.views.registration_form.AccountCreationForm(data=None, extra_fields=None, extended_profile_fields=None, do_third_party_auth=True, tos_required=True)#
Bases:
FormA form to for account creation data. It is currently only used for validation, not rendering.
- base_fields = {'email': <django.forms.fields.EmailField object>, 'name': <django.forms.fields.CharField object>, 'password': <django.forms.fields.CharField object>, 'username': <openedx.core.djangoapps.user_authn.views.registration_form.UsernameField object>}#
- clean_country()#
Check if the user’s country is in the embargoed countries list.
- clean_email()#
Enforce email restrictions (if applicable)
- clean_password()#
Enforce password policies (if applicable)
- clean_year_of_birth()#
Parse year_of_birth to an integer, but just use None instead of raising an error if it is malformed
- property cleaned_extended_profile#
Return a dictionary containing the extended_profile_fields and values
- declared_fields = {'email': <django.forms.fields.EmailField object>, 'name': <django.forms.fields.CharField object>, 'password': <django.forms.fields.CharField object>, 'username': <openedx.core.djangoapps.user_authn.views.registration_form.UsernameField object>}#
- property media#
Return all media required to render the widgets on this form.
- class openedx.core.djangoapps.user_authn.views.registration_form.RegistrationFormFactory#
Bases:
objectConstruct Registration forms and associated fields.
- DEFAULT_FIELDS = ['email', 'name', 'username', 'password']#
- get_registration_form(request)#
Return a description of the registration form. This decouples clients from the API definition: if the API decides to modify the form, clients won’t need to be updated. This is especially important for the registration form, since different edx-platform installations might collect different demographic information. See user_api.helpers.FormDescription for examples of the JSON-encoded form description. :param request: :type request: HttpRequest
- Returns:
HttpResponse
- class openedx.core.djangoapps.user_authn.views.registration_form.TrueCheckbox(attrs=None, check_test=None)#
Bases:
CheckboxInputA checkbox widget that only accepts “true” (case-insensitive) as true.
- property media#
- value_from_datadict(data, files, name)#
Given a dictionary of data and this widget’s name, return the value of this widget or None if it’s not provided.
- class openedx.core.djangoapps.user_authn.views.registration_form.TrueField(*, required=True, widget=None, label=None, initial=None, help_text='', error_messages=None, show_hidden_initial=False, validators=(), localize=False, disabled=False, label_suffix=None, template_name=None, bound_field_class=None)#
Bases:
BooleanFieldA boolean field that only accepts “true” (case-insensitive) as true
- widget#
alias of
TrueCheckbox
- class openedx.core.djangoapps.user_authn.views.registration_form.UsernameField(*args, **kwargs)#
Bases:
CharFieldA CharField that validates usernames based on the ENABLE_UNICODE_USERNAME feature.
- clean(value)#
Strips the spaces from the username.
Similar to what django.forms.SlugField does.
- default_validators = [<function validate_username>]#
- openedx.core.djangoapps.user_authn.views.registration_form.contains_html(value)#
Validator method to check whether name contains html tags
- openedx.core.djangoapps.user_authn.views.registration_form.contains_url(value)#
Validator method to check whether full name contains url
- openedx.core.djangoapps.user_authn.views.registration_form.get_extended_profile_model() type[Model] | None#
Get the model class for the extended profile form.
Returns the Django model class associated with the form specified in the PROFILE_EXTENSION_FORM setting.
IMPORTANT: This function only works with PROFILE_EXTENSION_FORM. If you’re using the deprecated REGISTRATION_EXTENSION_FORM, this will return None to maintain backward compatibility. The new profile extension capabilities (loading/saving to a custom model) are only available when using PROFILE_EXTENSION_FORM.
Migration path: - Old behavior (REGISTRATION_EXTENSION_FORM): Custom fields only for registration,
data stored in UserProfile.meta field
New behavior (PROFILE_EXTENSION_FORM): Custom fields for registration and profile, data stored in dedicated model with ability to load/update via account settings API
- Returns:
- The model class if PROFILE_EXTENSION_FORM is configured
and valid, None otherwise (including when using the deprecated REGISTRATION_EXTENSION_FORM).
- Return type:
Examples
# New setting with model support: # In settings.py: PROFILE_EXTENSION_FORM = ‘myapp.forms.ExtendedProfileForm’ model_class = get_extended_profile_model() # Returns the model
# Deprecated setting - maintains old behavior: # In settings.py: REGISTRATION_EXTENSION_FORM = ‘myapp.forms.ExtendedForm’ model_class = get_extended_profile_model() # Returns None (no model support)
- openedx.core.djangoapps.user_authn.views.registration_form.get_registration_extension_form(*args, **kwargs) Form | None#
Convenience function for getting the custom form set in settings.PROFILE_EXTENSION_FORM or settings.REGISTRATION_EXTENSION_FORM (deprecated).
Returns an instance of the configured profile extension form.
The function first checks for PROFILE_EXTENSION_FORM (recommended), then falls back to REGISTRATION_EXTENSION_FORM for backwards compatibility. When REGISTRATION_EXTENSION_FORM is used, a deprecation warning is logged.
An example form app for this can be found at open-craft/custom-form-app
- Returns:
Form instance or None if no form is configured
- openedx.core.djangoapps.user_authn.views.registration_form.validate_name(name)#
Verifies a Full_Name is valid, raises a ValidationError otherwise. :param name: The name to validate. :type name: unicode
- openedx.core.djangoapps.user_authn.views.registration_form.validate_username(username)#
Verifies a username is valid, raises a ValidationError otherwise. :param username: The username to validate. :type username: unicode
This function is configurable with ENABLE_UNICODE_USERNAME feature.
openedx.core.djangoapps.user_authn.views.utils module#
User Auth Views Utils
- openedx.core.djangoapps.user_authn.views.utils.get_auto_generated_username(data)#
Generate username based on learner’s name initials, current date and configurable random string.
This function creates a username in the format <name_initials>_<YYMM>_<configurable_random_string>
The length of random string is determined by AUTO_GENERATED_USERNAME_RANDOM_STRING_LENGTH setting.
Args:
data (dict): Registration payload.
Returns: - str: username.
- openedx.core.djangoapps.user_authn.views.utils.get_mfe_context(request, redirect_to, tpa_hint=None)#
Returns Authn MFE context.
- openedx.core.djangoapps.user_authn.views.utils.remove_disabled_country_from_list(countries: Dict) Dict#
Remove disabled countries from the list of countries.
Args: - countries (dict): List of countries.
Returns: - dict: Dict of countries with disabled countries removed.
- openedx.core.djangoapps.user_authn.views.utils.third_party_auth_context(request, redirect_to, tpa_hint=None)#
Context for third party auth providers and the currently running pipeline.
- Parameters:
request (HttpRequest) – The request, used to determine if a pipeline is currently running.
redirect_to – The URL to send the user to following successful authentication.
tpa_hint (string) – An override flag that will return a matching provider as long as its configuration has been enabled
- Returns:
dict