Skip to content

Commit

Permalink
SessionNoAuthTokenAuthentication custom authenticator (#53850)
Browse files Browse the repository at this point in the history
<!-- Describe your PR here. -->



<!--

  Sentry employees and contractors can delete or ignore the following.

-->

### Legal Boilerplate

Look, I get it. The entity doing business as "Sentry" was incorporated
in the State of Delaware in 2015 as Functional Software, Inc. and is
gonna need some rights from me in order to utilize my contributions in
this here PR. So here's the deal: I retain all rights, title and
interest in and to my contributions, and by keeping this boilerplate
intact I confirm that Sentry can use, modify, copy, and redistribute my
contributions, under Sentry's choice of terms.
  • Loading branch information
oioki authored Jul 31, 2023
1 parent 774af7d commit fad12c1
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 3 deletions.
14 changes: 13 additions & 1 deletion src/sentry/api/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
from django.contrib.auth.models import AnonymousUser
from django.utils.crypto import constant_time_compare
from django.utils.encoding import force_str
from rest_framework.authentication import BasicAuthentication, get_authorization_header
from rest_framework.authentication import (
BasicAuthentication,
SessionAuthentication,
get_authorization_header,
)
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.request import Request
from sentry_relay import UnpackError
Expand Down Expand Up @@ -157,6 +161,14 @@ def authenticate_credentials(self, userid, password, request=None):
return (AnonymousUser(), key)


class SessionNoAuthTokenAuthentication(SessionAuthentication):
def authenticate(self, request: Request):
auth = get_authorization_header(request)
if auth:
return None
return super().authenticate(request)


class ClientIdSecretAuthentication(QuietBasicAuthentication):
"""
Authenticates a Sentry Application using its Client ID and Secret
Expand Down
4 changes: 2 additions & 2 deletions src/sentry/api/endpoints/api_tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from rest_framework import serializers
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.response import Response

from sentry import analytics
from sentry.api.authentication import SessionNoAuthTokenAuthentication
from sentry.api.base import Endpoint, control_silo_endpoint
from sentry.api.fields import MultipleChoiceField
from sentry.api.serializers import serialize
Expand All @@ -22,7 +22,7 @@ class ApiTokenSerializer(serializers.Serializer):

@control_silo_endpoint
class ApiTokensEndpoint(Endpoint):
authentication_classes = (SessionAuthentication,)
authentication_classes = (SessionNoAuthTokenAuthentication,)
permission_classes = (IsAuthenticated,)

@method_decorator(never_cache)
Expand Down
7 changes: 7 additions & 0 deletions tests/sentry/api/endpoints/test_api_tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ def test_never_cache(self):
== "max-age=0, no-cache, no-store, must-revalidate, private"
)

def test_deny_token_access(self):
token = ApiToken.objects.create(user=self.user, scope_list=[])

url = reverse("sentry-api-0-api-tokens")
response = self.client.get(url, format="json", HTTP_AUTHORIZATION=f"Bearer {token.token}")
assert response.status_code == 403, response.content


@control_silo_test(stable=True)
class ApiTokensCreateTest(APITestCase):
Expand Down

0 comments on commit fad12c1

Please sign in to comment.