Third Party Auth Customization

I have enabled third party auth with my external app , Now what i want to achieve is if the user is already registered and verifieid on external app , it should automatically register that user on openedx platform when it try to sign in for the first time. The details that i get from external app does not include full name which is necessary for registration so openedx platform ultimately lands up in a web error.

I already have an idea how to reolve this error. I can add a function in social_auth_pipeline which will create full name from first name and last name.

I want suggestions on how can I resolve this issue using plugin or hook or filter.

I added django app in the lms container and installed it with pip , when i do pip list, it shows up.

Here are the contents

/openedx/edx-platform/requirements/fullnamepipeline/fullnamepipeline/pipeline.py
import logging

logger = logging.getLogger(name)

def add_full_name(strategy, details, *args, **kwargs):
“”"
Social-auth pipeline step: ensure details[‘fullname’] is ‘First Last’.
“”"
logger.warning(“:white_check_mark: FULLNAMEPIPELINE CALLED for user %s”, details)
first = (details.get(“first_name”) or “”).strip()
last = (details.get(“last_name”) or “”).strip()
full = f"{first} {last}".strip()
full = “FUll name”

Only set fullname if we actually built something

if full:

Either mutate in place or return an update dict; both are acceptable.

details[“fullname”] = full
return {“details”: details}
return None

requirements/fullnamepipeline/setup.py

from setuptools import setup, find_packages

setup(
name=“fullnamepipeline”,
version=“0.1.0”,
packages=find_packages(),
include_package_data=True,
install_requires=[
“edx-django-utils>=8.0.0”,
“social-auth-core”, # already in edx-platform, but harmless here
],
entry_points={
“lms.djangoapp”: [
“fullnamepipeline = fullnamepipeline.apps:FullNamePipelineConfig”,
],
“cms.djangoapp”: [
“fullnamepipeline = fullnamepipeline.apps:FullNamePipelineConfig”,
],
},
)

**requirements/fullnamepipeline/fullnamepipeline/apps.py
**
from django.apps import AppConfig
from edx_django_utils.plugins.constants import PluginSettings

class FullNamePipelineConfig(AppConfig):
name = “fullnamepipeline”
verbose_name = “Full Name Pipeline”

# Tell edx-platform this plugin has settings to merge
plugin_app = {
    PluginSettings.CONFIG: {
        "lms.djangoapp": {
            "common": {PluginSettings.RELATIVE_PATH: "settings.common"},
        },
        "cms.djangoapp": {
            "common": {PluginSettings.RELATIVE_PATH: "settings.common"},
        },
    }
}

requirements/fullnamepipeline/fullnamepipeline/settings/common.py

def plugin_settings(settings):
“”"
Insert our step right after the built-in social_details step.
“”"
anchor = “common.djangoapps.third_party_auth.pipeline.associate_by_email_if_oauth”
step = “fullnamepipeline.pipeline.add_full_name”

pipeline = list(getattr(settings, "SOCIAL_AUTH_PIPELINE", ()))
if step not in pipeline:
    try:
        i = pipeline.index(anchor)
        pipeline.insert(i + 1, step)
    except ValueError:
        # Fallback: append if anchor not found
        pipeline.append(step)
settings.SOCIAL_AUTH_PIPELINE = tuple(pipeline)

requirements/fullnamepipeline/fullnamepipeline/_init_.py

Hi @neel1 - I’m not sure how to advise you on this, I unfortunately don’t know who is an expert on third party auth in the community.

Hi @sarina , Thank you for the response. However my question is not just aimed at third party auth. I wanted to know how django app plugins work. If I have to patch some code through plugin, would I be able to do that. In the problem that I have mentioned above, I had a requirement of modifying an existing variable in the django app code named SOCIAL_AUTH_PIPELINE and add a function and define that function in the plugin itself . Is it possible to do so through plugin ? If not what is the best way to do that?

Thanks in advance!

I wanted to know how django app plugins work.

@feanil I know you’ve been looking at plugins. Do you know the best set of documentation I could point at here to help @neel1 out?

@neel1 you’ve totally got the right idea, From the settings setup, you can update the existing settings and those changes will update the base settings. You definitely have to be careful with this because you could break settings if your overrwrite without understanding what’s going on (adding better safety around this would be nice but no one has had time to work on that yet). What you’re doing in your example makes sense and should work.

In terms of plugin docs, currently we have: How to create a plugin app — edx-django-utils 8.0.0 documentation

Which I welcome changes and improvements to if you’re interested in contributing to it.

@feanil thank you for your response. What I have observed is if I try to override/change any of envs in cms/envs/common.py or lms/envs/common.py , it is successful. However if I override any of the settings in common/djangoapps, those get set before these djangoapps and those originial source code overrides it. eg SOCIAL_AUTH_PIPELINE is defined in ThirdPartyAuthConfig and thus it overrides my changes in my plugin.

Here is the source code-

class ThirdPartyAuthConfig(AppConfig): # lint-amnesty, pylint: disable=missing-class-docstring

name = 'common.djangoapps.third_party_auth'

verbose_name = “Third-party authentication”

def ready(self):

# Import signal handlers to register them

from .signals import handlers # noqa: F401 pylint: disable=unused-import

# To override the settings before loading social_django.

if settings.FEATURES.get(‘ENABLE_THIRD_PARTY_AUTH’, False):

self._enable_third_party_auth()

def _enable_third_party_auth(self):

“”"

    Enable the use of third_party_auth, which allows users to sign in to edX

    using other identity providers. For configuration details, see

    common/djangoapps/third_party_auth/settings.py.

    """

from common.djangoapps.third_party_auth import settings as auth_settings

auth_settings.apply_settings(settings)

def apply_settings(django_settings):

django_settings.SOCIAL_AUTH_PIPELINE = [

    'common.djangoapps.third_party_auth.pipeline.parse_query_params',


]

Summary

This text will be hidden

@neel1 thanks for pointing this out! This is some old crufty code and is clearly a work_around that we need to undo. In the past, the way settings were loaded in edx-platform was even more convoluted than it is today and so it looks like this app uses the ENABLE_THIRD_PART_AUTH flag to determine whether or not to override settings that exist in the main settings file as a part of the startup process. I think all of the code in apply_settings file can just live in a conditional in the common top-level settings file and provide a way for you to update the pipelines.

These settings should not be updated during the app loading or if they remain there, they should provide a way for you to further override them. If you’re willing to make a PR to move the settings from the apply_settings function up to the lms/envs/common.py settings file, I’m happy to help review and get that change landed.