-
-
Notifications
You must be signed in to change notification settings - Fork 165
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixed public API authentication for teams. Now works with new Python …
…Client Signed-off-by: Trey <[email protected]>
- Loading branch information
Showing
7 changed files
with
56 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,66 @@ | ||
from typing import Type | ||
|
||
from rest_framework.authentication import TokenAuthentication | ||
from rest_framework.authentication import TokenAuthentication, get_authorization_header | ||
from rest_framework.exceptions import AuthenticationFailed | ||
|
||
from django.utils.translation import gettext_lazy as _ | ||
from backend.core.api.public.models import APIAuthToken | ||
from backend.models import User, Organization | ||
|
||
from rest_framework import exceptions | ||
|
||
|
||
class CustomBearerAuthentication(TokenAuthentication): | ||
keyword = "Bearer" | ||
|
||
def get_model(self) -> Type[APIAuthToken]: | ||
return APIAuthToken | ||
|
||
def authenticate(self, request): | ||
auth = get_authorization_header(request).split() | ||
|
||
if not auth or auth[0].lower() != self.keyword.lower().encode(): | ||
return None | ||
|
||
if len(auth) == 1: | ||
msg = _("Invalid token header. No credentials provided.") | ||
raise exceptions.AuthenticationFailed(msg) | ||
elif len(auth) > 2: | ||
msg = _("Invalid token header. Token string should not contain spaces.") | ||
raise exceptions.AuthenticationFailed(msg) | ||
|
||
try: | ||
token = auth[1].decode() | ||
except UnicodeError: | ||
msg = _("Invalid token header. Token string should not contain invalid characters.") | ||
raise exceptions.AuthenticationFailed(msg) | ||
|
||
user_or_org, token = self.authenticate_credentials(token) | ||
|
||
request.actor = user_or_org | ||
|
||
if isinstance(user_or_org, Organization): | ||
request.team = user_or_org | ||
request.team_id = user_or_org.id | ||
else: | ||
request.team = None | ||
request.team_id = None | ||
|
||
return (user_or_org, token) | ||
|
||
def authenticate_credentials(self, raw_key) -> tuple[User | Organization | None, APIAuthToken]: | ||
model = self.get_model() | ||
|
||
try: | ||
token = model.objects.get(hashed_key=model.hash_raw_key(raw_key), active=True) | ||
except model.DoesNotExist: | ||
raise AuthenticationFailed("Invalid token.") | ||
raise AuthenticationFailed(_("Invalid token.")) | ||
|
||
if token.has_expired: | ||
raise AuthenticationFailed("Token has expired.") | ||
raise AuthenticationFailed(_("Token has expired.")) | ||
|
||
user_or_org = token.user or token.organization | ||
|
||
# todo: make sure this is safe to set request.user = <Team> obj | ||
return token.user or token.organization, token | ||
if user_or_org is None: | ||
raise AuthenticationFailed(_("Associated user or organization not found.")) | ||
|
||
# todo: override more methods + add hashing | ||
return user_or_org, token |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +0,0 @@ | ||
from django.utils.deprecation import MiddlewareMixin | ||
|
||
from backend.core.api.public import APIAuthToken | ||
from backend.models import Organization | ||
|
||
|
||
class AttachTokenMiddleware(MiddlewareMixin): | ||
def process_request(self, request): | ||
if not request.path.startswith("/api/public/"): | ||
return | ||
|
||
auth_header = request.headers.get("Authorization") | ||
|
||
if not (auth_header and auth_header.startswith("Bearer ")): | ||
request.auth = None | ||
return | ||
|
||
token_key = auth_header.split(" ")[1] | ||
try: | ||
token = APIAuthToken.objects.get(key=token_key, active=True) | ||
if not token.has_expired: | ||
request.auth = token | ||
request.api_token = token | ||
except APIAuthToken.DoesNotExist: | ||
request.auth = None | ||
|
||
|
||
class HandleTeamContextMiddleware(MiddlewareMixin): | ||
def process_request(self, request): | ||
if not request.path.startswith("/api/public/"): | ||
return | ||
|
||
if hasattr(request, "query_params"): | ||
team_id = request.query_params.get("team_id") | ||
else: | ||
team_id = request.GET.get("team_id") | ||
request.team = None | ||
request.team_id = team_id | ||
|
||
if not team_id: | ||
# No team_id provided, proceed with user context | ||
return | ||
|
||
team = Organization.objects.filter(id=team_id).first() | ||
|
||
request.team = team | ||
request.actor = team | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters