Do not require authentication for OPTIONS requests
Question: My settings.py

    
    
    REST_FRAMEWORK = {
        'UNICODE_JSON': True,
        'NON_FIELD_ERRORS_KEY': '__all__',
        'DEFAULT_AUTHENTICATION_CLASSES': (
            # TODO(dmu) HIGH: Support OAuth or alike authentication
            'rest_framework.authentication.TokenAuthentication',
        ),
        'DEFAULT_PERMISSION_CLASSES': (
            'rest_framework.permissions.IsAuthenticated',
        ),
        'DEFAULT_RENDERER_CLASSES': (
            'rest_framework.renderers.JSONRenderer',
        ),
        'ALLOWED_VERSIONS': ['v1'],
        'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning',
        'TEST_REQUEST_DEFAULT_FORMAT': 'json',
        'TEST_REQUEST_RENDERER_CLASSES': (
            'rest_framework.renderers.JSONRenderer',
        )
    }
    

When I do this I get authentication error:

    
    
    curl -X OPTIONS http://127.0.0.1:8000/api/passenger/v1/order/ | python -m json.tool
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100    58    0    58    0     0    469      0 --:--:-- --:--:-- --:--:--   475
    {
        "detail": "Authentication credentials were not provided."
    }
    

I'd like my server respond with "schema" description and not required
authentication. At the same time I want it to require authentication for GET,
POST, PUT, PATCH and DELETE requests as usual.

How can I achieve that?

**MY SOLUTION**

Thank you, Alasdair, for the idea. I personally used this solution:

    
    
    from rest_framework.permissions import DjangoObjectPermissions
    
    OPTIONS_METHOD = 'OPTIONS'
    
    class DjangoObjectPermissionsOrOptions(DjangoObjectPermissions):
        def has_permission(self, request, view):
            if request.method == OPTIONS_METHOD:
                return True
            else:
                return super(DjangoObjectPermissions, self).has_permission(request, view)
    


Answer: Django rest framework comes with a permissions class
[`IsAuthenticatedOrReadOnly`](http://www.django-rest-framework.org/api-
guide/permissions/#isauthenticatedorreadonly), which allows authenticated
users to perform any request, and unauthorised users to make GET, HEAD or
OPTIONS requests.

Your use case is pretty similar, so you could try the following (untested):

    
    
    class IsAuthenticatedOrOptions(BasePermission):
        """
        The request is authenticated as a user, or an OPTIONS request.
        """
    
        def has_permission(self, request, view):
            return (
                request.method == 'OPTIONS' or
                request.user and
                request.user.is_authenticated()
            )
    
    'DEFAULT_PERMISSION_CLASSES': (
        'path.to.IsAuthenticatedOrOptions',
    ),
    

