68 lines
2.2 KiB
Python
68 lines
2.2 KiB
Python
"""
|
|
GraphQL middleware for JWT authentication.
|
|
|
|
Each class is bound to a specific GraphQL endpoint (public/user/team).
|
|
"""
|
|
from django.conf import settings
|
|
from graphql import GraphQLError
|
|
from jwt import InvalidTokenError
|
|
|
|
from .auth import get_bearer_token, scopes_from_payload, validator
|
|
|
|
|
|
def _is_introspection(info) -> bool:
|
|
"""Возвращает True для любых introspection резолвов."""
|
|
field = getattr(info, "field_name", "")
|
|
parent = getattr(getattr(info, "parent_type", None), "name", "")
|
|
return field.startswith("__") or parent.startswith("__")
|
|
|
|
|
|
class PublicNoAuthMiddleware:
|
|
"""Public endpoint - no authentication required."""
|
|
|
|
def resolve(self, next, root, info, **kwargs):
|
|
return next(root, info, **kwargs)
|
|
|
|
|
|
class UserJWTMiddleware:
|
|
"""User endpoint - requires ID token."""
|
|
|
|
def resolve(self, next, root, info, **kwargs):
|
|
request = info.context
|
|
if _is_introspection(info):
|
|
return next(root, info, **kwargs)
|
|
|
|
try:
|
|
token = get_bearer_token(request)
|
|
payload = validator.decode(token)
|
|
request.user_id = payload.get('sub')
|
|
except InvalidTokenError as exc:
|
|
raise GraphQLError("Unauthorized") from exc
|
|
|
|
return next(root, info, **kwargs)
|
|
|
|
|
|
class TeamJWTMiddleware:
|
|
"""Team endpoint - requires Access token for orders audience."""
|
|
|
|
def resolve(self, next, root, info, **kwargs):
|
|
request = info.context
|
|
if _is_introspection(info):
|
|
return next(root, info, **kwargs)
|
|
|
|
try:
|
|
token = get_bearer_token(request)
|
|
payload = validator.decode(
|
|
token,
|
|
audience=getattr(settings, 'LOGTO_ORDERS_AUDIENCE', None),
|
|
)
|
|
request.user_id = payload.get('sub')
|
|
request.team_uuid = payload.get('team_uuid') # Custom claim from Logto
|
|
request.scopes = scopes_from_payload(payload)
|
|
if not request.team_uuid or 'teams:member' not in request.scopes:
|
|
raise GraphQLError("Unauthorized")
|
|
except InvalidTokenError as exc:
|
|
raise GraphQLError("Unauthorized") from exc
|
|
|
|
return next(root, info, **kwargs)
|