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.
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.