Skip to content

RemoteUserAuthentication, docs, and tests #5306

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions docs/api-guide/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,28 @@ If you're using an AJAX style API with SessionAuthentication, you'll need to mak

CSRF validation in REST framework works slightly differently to standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behaviour is not suitable for login views, which should always have CSRF validation applied.


## RemoteUserAuthentication

This authentication scheme allows you to delegate authentication to your web server, which sets the `REMOTE_USER`
environment variable.

To use it, you must have `django.contrib.auth.backends.RemoteUserBackend` (or a subclass) in your
`AUTHENTICATION_BACKENDS` setting. By default, `RemoteUserBackend` creates `User` objects for usernames that don't
already exist. To change this and other behaviour, consult the
[Django documentation](https://docs.djangoproject.com/en/stable/howto/auth-remote-user/).

If successfully authenticated, `RemoteUserAuthentication` provides the following credentials:

* `request.user` will be a Django `User` instance.
* `request.auth` will be `None`.

Consult your web server's documentation for information about configuring an authentication method, e.g.:

* [Apache Authentication How-To](https://httpd.apache.org/docs/2.4/howto/auth.html)
* [NGINX (Restricting Access)](https://www.nginx.com/resources/admin-guide/#restricting_access)


# Custom authentication

To implement a custom authentication scheme, subclass `BaseAuthentication` and override the `.authenticate(self, request)` method. The method should return a two-tuple of `(user, auth)` if authentication succeeds, or `None` otherwise.
Expand Down
21 changes: 21 additions & 0 deletions rest_framework/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,24 @@ def authenticate_credentials(self, key):

def authenticate_header(self, request):
return self.keyword


class RemoteUserAuthentication(BaseAuthentication):
"""
REMOTE_USER authentication.

To use this, set up your web server to perform authentication, which will
set the REMOTE_USER environment variable. You will need to have
'django.contrib.auth.backends.RemoteUserBackend in your
AUTHENTICATION_BACKENDS setting
"""

# Name of request header to grab username from. This will be the key as
# used in the request.META dictionary, i.e. the normalization of headers to
# all uppercase and the addition of "HTTP_" prefix apply.
header = "REMOTE_USER"

def authenticate(self, request):
user = authenticate(remote_user=request.META.get(self.header))
if user and user.is_active:
return (user, None)
26 changes: 23 additions & 3 deletions tests/test_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@
HTTP_HEADER_ENCODING, exceptions, permissions, renderers, status
)
from rest_framework.authentication import (
BaseAuthentication, BasicAuthentication, SessionAuthentication,
TokenAuthentication
)
BaseAuthentication, BasicAuthentication, RemoteUserAuthentication, SessionAuthentication,
TokenAuthentication)
from rest_framework.authtoken.models import Token
from rest_framework.authtoken.views import obtain_auth_token
from rest_framework.compat import is_authenticated
Expand Down Expand Up @@ -64,6 +63,10 @@ def put(self, request):
r'^basic/$',
MockView.as_view(authentication_classes=[BasicAuthentication])
),
url(
r'^remote-user/$',
MockView.as_view(authentication_classes=[RemoteUserAuthentication])
),
url(
r'^token/$',
MockView.as_view(authentication_classes=[TokenAuthentication])
Expand Down Expand Up @@ -523,3 +526,20 @@ class MockUser(object):
auth.authenticate_credentials('foo', 'bar')
assert 'User inactive or deleted.' in str(error)
authentication.authenticate = old_authenticate


@override_settings(ROOT_URLCONF='tests.test_authentication',
AUTHENTICATION_BACKENDS=('django.contrib.auth.backends.RemoteUserBackend',))
class RemoteUserAuthenticationUnitTests(TestCase):
def setUp(self):
self.username = 'john'
self.email = 'lennon@thebeatles.com'
self.password = 'password'
self.user = User.objects.create_user(
self.username, self.email, self.password
)

def test_remote_user_works(self):
response = self.client.post('/remote-user/',
REMOTE_USER=self.username)
self.assertEqual(response.status_code, status.HTTP_200_OK)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy