GeoNode / geonode

GeoNode is an open source platform that facilitates the creation, sharing, and collaborative use of geospatial data.
https://geonode.org/
Other
1.43k stars 1.12k forks source link

providing multiple openid_connect django.allauth socialproviders fails when loading login page #12167

Open mwallschlaeger opened 4 months ago

mwallschlaeger commented 4 months ago

Expected Behavior

When defining multiple openid_connect APPS within the SOCIALACCOUNT_PROVIDERS in settings.py like e.g. defined in the allauth docs:

SOCIALACCOUNT_PROVIDERS = {
    "openid_connect": {
        "APPS": [
            {
                "provider_id": "my-server",
                "name": "My Login Server",
                "client_id": "your.service.id",
                "secret": "your.service.secret",
                "settings": {
                    "server_url": "https://my.server.example.com",
                    # Optional token endpoint authentication method.
                    # May be one of "client_secret_basic", "client_secret_post"
                    # If omitted, a method from the the server's
                    # token auth methods list is used
                    "token_auth_method": "client_secret_basic",
                },
            },
            {
                "provider_id": "other-server",
                "name": "Other Login Server",
                "client_id": "your.other.service.id",
                "secret": "your.other.service.secret",
                "settings": {
                    "server_url": "https://other.server.example.com",
                },
            },
        ]
    }
}

I would expect that, after i configured the socialaccountapps inside the admin-interface that i would have multiple options as social providers.

Actual Behavior

Actually, after configuring the social providers, I run into the following exception when opening /login:

traceback ``` File "/usr/src/geonode/./geonode/views.py", line 110, in handler500 response = render(request, template_name) File "/usr/local/lib/python3.10/dist-packages/sentry_sdk/integrations/django/templates.py", line 102, in render return real_render(request, template_name, context, *args, **kwargs) File "/usr/local/lib/python3.10/dist-packages/django/shortcuts.py", line 19, in render content = loader.render_to_string(template_name, context, request, using=using) File "/usr/local/lib/python3.10/dist-packages/django/template/loader.py", line 62, in render_to_string return template.render(context, request) File "/usr/local/lib/python3.10/dist-packages/django/template/backends/django.py", line 61, in render return self.template.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 170, in render return self._render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 162, in _render return self.nodelist.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/loader_tags.py", line 150, in render return compiled_parent._render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 162, in _render return self.nodelist.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/loader_tags.py", line 150, in render return compiled_parent._render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 162, in _render return self.nodelist.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/loader_tags.py", line 150, in render return compiled_parent._render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 162, in _render return self.nodelist.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/defaulttags.py", line 315, in render return nodelist.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/defaulttags.py", line 315, in render return nodelist.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/loader_tags.py", line 195, in render return template.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 172, in render return self._render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 162, in _render return self.nodelist.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/defaulttags.py", line 214, in render nodelist.append(node.render_annotated(context)) File "/usr/local/lib/python3.10/dist-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/usr/local/lib/python3.10/dist-packages/django/template/library.py", line 192, in render output = self.func(*resolved_args, **resolved_kwargs) File "/usr/local/lib/python3.10/dist-packages/allauth/socialaccount/templatetags/socialaccount.py", line 20, in provider_login_url provider = adapter.get_provider(request, provider) File "/usr/src/geonode/./geonode/people/adapters.py", line 270, in get_provider app = self.get_app(request, provider=provider) File "/usr/local/lib/python3.10/dist-packages/allauth/socialaccount/adapter.py", line 301, in get_app raise MultipleObjectsReturned django.core.exceptions.MultipleObjectsReturned ```

django.allauth docs describe that for each APP allauth will "create an independent provider instances". Therefor the geonode adapter need to distinguish between the different APPS when passing them to the get_provider() function in

https://github.com/GeoNode/geonode/blob/75edcdb50417f96d858b25b46a0998db6fe2ec14/geonode/people/adapters.py#L270

This could be done by passing the optional parameter client_id=self.get_apps_list([0].client_id)

Specifications

afabiani commented 4 months ago

Uhm, I guess the adapter should be also improved in order to correctly fetch the additional properties from the selected provider. Currently it assumes having just one provider.