Repository: django-oscar/django-oscar

Issue:
Request not being passed to authenticate method
### Issue Summary

Django-oscar's [`EmailAuthenticationForm`](https://github.com/django-oscar/django-oscar/blob/master/src/oscar/apps/customer/forms.py#L76) is a subclass of Django's [`AuthenticationForm`](https://github.com/django/django/blob/master/django/contrib/auth/forms.py#L163).
When calling `clean` method, django `authenticate` is called without `request` object.

Looking [at the code](https://github.com/django-oscar/django-oscar/blob/master/src/oscar/apps/customer/views.py#L136), the `AccountAuthView` is not passing the `request` object to the Form.

Some custom backend, like django-axes's, requires that in order to work properly.
That's why [this issue](https://github.com/django-oscar/django-oscar/issues/2111) was happening

### Steps to Reproduce

1. Create a simple authentication backend that requires the `request` object, and put it before django-oscar's backend:

```
# project/backends.py

from django.contrib.auth.backends import ModelBackend


class CustomBackend(ModelBackend):
    def authenticate(self, request, username: str = None, password: str = None, **kwargs: dict):
        

        if request is None:
            raise Exception('CustomBackend requires a request as an argument to authenticate')
       # some logic

# On settings

AUTHENTICATION_BACKENDS = [
    'project.backends.CustomBackend',
    'oscar.apps.customer.auth_backends.EmailBackend',
]

```
2. Try to login
3. Observe `Exception('CustomBackend requires a request as an argument to authenticate')` is raised


### Technical details

```
$ python --version
Python 3.7.4
$ pip freeze | grep Django
Django==2.2.6
$ pip freeze | grep django-oscar
django-oscar==2.0.3
```


Discussion:

Resolving patch:
diff --git a/src/oscar/apps/customer/views.py b/src/oscar/apps/customer/views.py
--- a/src/oscar/apps/customer/views.py
+++ b/src/oscar/apps/customer/views.py
@@ -135,6 +135,7 @@ def get_login_form(self, bind_data=False):
 
     def get_login_form_kwargs(self, bind_data=False):
         kwargs = {}
+        kwargs['request'] = self.request
         kwargs['host'] = self.request.get_host()
         kwargs['prefix'] = self.login_prefix
         kwargs['initial'] = {


Test patch:
diff --git a/tests/unit/customer/test_views.py b/tests/unit/customer/test_views.py
new file mode 100644
--- /dev/null
+++ b/tests/unit/customer/test_views.py
@@ -0,0 +1,28 @@
+from unittest.mock import Mock, patch
+
+from django.test import Client, TestCase
+from django.urls import reverse
+
+from oscar.apps.customer.forms import EmailAuthenticationForm
+
+
+class TestAccountAuthView(TestCase):
+
+    def setUp(self):
+        self.client = Client()
+
+    def test_request_is_passed_to_form(self):
+        form_class = Mock(wraps=EmailAuthenticationForm)
+        data = {"login_submit": ["1"]}
+        initial = {'redirect_url': ''}
+        with patch("oscar.apps.customer.views.AccountAuthView.login_form_class", new=form_class):
+            response = self.client.post(reverse("customer:login"), data=data)
+            assert form_class.called
+            form_class.assert_called_with(
+                data=data,
+                files={},
+                host="testserver",
+                initial=initial,
+                prefix='login',
+                request=response.wsgi_request,
+            )