I’m getting started with dj-rest-auth and I have an app which allows user to only sign in via google. However, I want users to only be able to access my service with a specific google apps email domain.
I’m using dj-rest-auth in conjunction with django-allauth.
This is what I tried: I created allauth adapters like this:
class CustomAccountAdapter(DefaultAccountAdapter): def is_open_for_signup(self, request): return False # No email/password signups allowed class CustomSocialAccountAdapter(DefaultSocialAccountAdapter): def is_open_for_signup(self, request, socialaccount): u = socialaccount.user return u.email.split("@")[1] == "mydomain.com"
and in my settings I have
ACCOUNT_ADAPTER = "users.adapters.CustomAccountAdapter" SOCIALACCOUNT_ADAPTER = "users.adapters.CustomSocialAccountAdapter"
With this solution, if the user tries to sign in with a valid email, everything works, whereas if they use a non-allowed email domain, I get this error in my console:
Traceback (most recent call last): File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner response = get_response(request) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view return view_func(*args, **kwargs) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view return self.dispatch(request, *args, **kwargs) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/utils/decorators.py", line 43, in _wrapper return bound_method(*args, **kwargs) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/views/decorators/debug.py", line 89, in sensitive_post_parameters_wrapper return view(request, *args, **kwargs) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/dj_rest_auth/views.py", line 48, in dispatch return super(LoginView, self).dispatch(*args, **kwargs) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/rest_framework/views.py", line 505, in dispatch response = self.handle_exception(exc) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/rest_framework/views.py", line 465, in handle_exception self.raise_uncaught_exception(exc) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/rest_framework/views.py", line 476, in raise_uncaught_exception raise exc File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/rest_framework/views.py", line 502, in dispatch response = handler(request, *args, **kwargs) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/dj_rest_auth/views.py", line 138, in post self.serializer.is_valid(raise_exception=True) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/rest_framework/serializers.py", line 234, in is_valid self._validated_data = self.run_validation(self.initial_data) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/rest_framework/serializers.py", line 436, in run_validation value = self.validate(value) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/dj_rest_auth/registration/serializers.py", line 134, in validate complete_social_login(request, login) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/allauth/socialaccount/helpers.py", line 151, in complete_social_login return _complete_social_login(request, sociallogin) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/allauth/socialaccount/helpers.py", line 172, in _complete_social_login ret = _process_signup(request, sociallogin) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/allauth/socialaccount/helpers.py", line 38, in _process_signup return render( File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/shortcuts.py", line 19, in render content = loader.render_to_string(template_name, context, request, using=using) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/loader.py", line 62, in render_to_string return template.render(context, request) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/backends/django.py", line 61, in render return self.template.render(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py", line 170, in render return self._render(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/test/utils.py", line 96, in instrumented_test_render return self.nodelist.render(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/loader_tags.py", line 150, in render return compiled_parent._render(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/test/utils.py", line 96, in instrumented_test_render return self.nodelist.render(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/loader_tags.py", line 62, in render result = block.nodelist.render(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/defaulttags.py", line 312, in render return nodelist.render(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/defaulttags.py", line 446, in render url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/urls/base.py", line 87, in reverse return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)) File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/urls/resolvers.py", line 685, in _reverse_with_prefix raise NoReverseMatch(msg) django.urls.exceptions.NoReverseMatch: Reverse for 'account_login' not found. 'account_login' is not a valid view function or pattern name. [17/Mar/2021 18:49:42] "POST /dj-rest-auth/google HTTP/1.1" 500 246781
What I would like to do is for my django app to send a 403 response to the user (or similar) with a message like “You can only access this service with an [at] whatever email address”. I’m trying to figure out at which point the dj-rest-auth views call the user adapters and what to do to handle the failure and achieve what I’m after.
Advertisement
Answer
When you return is_open_for_signup==False, internally django-allauth returns a template:
if not get_adapter(request).is_open_for_signup(request, sociallogin): return render( request, "account/signup_closed." + account_settings.TEMPLATE_EXTENSION, )
That template extends a template account/base.html (inside django-allauth project) and in this template you have the problematic URL defined <li><a href="{% url 'account_login' %}">Sign In</a></li>
You can override your signup_closed.html template and solve this error, but if you need to return a Json (because of the API), you should use your own implementation of django-allauth.