Merge pull request #1961 from ryanpetrello/fix-1672

don't allow Accept:application/json on /api/login/
This commit is contained in:
Ryan Petrello 2018-05-25 16:55:11 -04:00 committed by GitHub
commit 0fca495792
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 2 deletions

View File

@ -24,13 +24,14 @@ from django.contrib.auth import views as auth_views
# Django REST Framework
from rest_framework.authentication import get_authorization_header
from rest_framework.exceptions import PermissionDenied, AuthenticationFailed, ParseError
from rest_framework.exceptions import PermissionDenied, AuthenticationFailed, ParseError, NotAcceptable
from rest_framework import generics
from rest_framework.response import Response
from rest_framework import status
from rest_framework import views
from rest_framework.permissions import AllowAny
from rest_framework.renderers import JSONRenderer
from rest_framework.renderers import StaticHTMLRenderer, JSONRenderer
from rest_framework.negotiation import DefaultContentNegotiation
# cryptography
from cryptography.fernet import InvalidToken
@ -64,6 +65,25 @@ analytics_logger = logging.getLogger('awx.analytics.performance')
class LoggedLoginView(auth_views.LoginView):
def get(self, request, *args, **kwargs):
# The django.auth.contrib login form doesn't perform the content
# negotiation we've come to expect from DRF; add in code to catch
# situations where Accept != text/html (or */*) and reply with
# an HTTP 406
try:
DefaultContentNegotiation().select_renderer(
request,
[StaticHTMLRenderer],
'html'
)
except NotAcceptable:
resp = Response(status=status.HTTP_406_NOT_ACCEPTABLE)
resp.accepted_renderer = StaticHTMLRenderer()
resp.accepted_media_type = 'text/plain'
resp.renderer_context = {}
return resp
return super(LoggedLoginView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
original_user = getattr(request, 'user', None)
ret = super(LoggedLoginView, self).post(request, *args, **kwargs)

View File

@ -24,6 +24,20 @@ class AlwaysPassBackend(object):
return '{}.{}'.format(cls.__module__, cls.__name__)
@pytest.mark.django_db
@pytest.mark.parametrize('accept, status', [
['*/*', 200],
['text/html', 200],
['application/json', 406]
])
def test_login_json_not_allowed(get, accept, status):
get(
'/api/login/',
HTTP_ACCEPT=accept,
expect=status
)
@pytest.mark.skip(reason="Needs Update - CA")
@pytest.mark.django_db
def test_session_create_delete(admin, post, get):