sources/plex: allow auth for owner (when identifier of source plex token matches)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		| @ -149,6 +149,7 @@ class SourceFlowManager: | ||||
|     def get_flow(self, **kwargs) -> HttpResponse: | ||||
|         """Get the flow response based on user_matching_mode""" | ||||
|         action, connection = self.get_action() | ||||
|         self._logger.debug("get_action() says", action=action, connection=connection) | ||||
|         if connection: | ||||
|             if action == Action.LINK: | ||||
|                 self._logger.debug("Linking existing user") | ||||
|  | ||||
| @ -4,10 +4,12 @@ from django.shortcuts import get_object_or_404 | ||||
| from drf_yasg import openapi | ||||
| from drf_yasg.utils import swagger_auto_schema | ||||
| from rest_framework.decorators import action | ||||
| from rest_framework.exceptions import PermissionDenied | ||||
| from rest_framework.fields import CharField | ||||
| from rest_framework.permissions import AllowAny | ||||
| from rest_framework.request import Request | ||||
| from rest_framework.response import Response | ||||
| from rest_framework.serializers import ValidationError | ||||
| from rest_framework.viewsets import ModelViewSet | ||||
| from structlog.stdlib import get_logger | ||||
|  | ||||
| @ -15,6 +17,7 @@ from authentik.api.decorators import permission_required | ||||
| from authentik.core.api.sources import SourceSerializer | ||||
| from authentik.core.api.utils import PassiveSerializer | ||||
| from authentik.flows.challenge import RedirectChallenge | ||||
| from authentik.flows.views import to_stage_response | ||||
| from authentik.sources.plex.models import PlexSource | ||||
| from authentik.sources.plex.plex import PlexAuth, PlexSourceFlowManager | ||||
|  | ||||
| @ -51,7 +54,11 @@ class PlexSourceViewSet(ModelViewSet): | ||||
|     @permission_required(None) | ||||
|     @swagger_auto_schema( | ||||
|         request_body=PlexTokenRedeemSerializer(), | ||||
|         responses={200: RedirectChallenge(), 404: "Token not found"}, | ||||
|         responses={ | ||||
|             200: RedirectChallenge(), | ||||
|             400: "Token not found", | ||||
|             403: "Access denied", | ||||
|         }, | ||||
|         manual_parameters=[ | ||||
|             openapi.Parameter( | ||||
|                 name="slug", | ||||
| @ -75,13 +82,15 @@ class PlexSourceViewSet(ModelViewSet): | ||||
|         ) | ||||
|         plex_token = request.data.get("plex_token", None) | ||||
|         if not plex_token: | ||||
|             raise Http404 | ||||
|             raise ValidationError("No plex token given") | ||||
|         auth_api = PlexAuth(source, plex_token) | ||||
|         user_info, identifier = auth_api.get_user_info() | ||||
|         # Check friendship first, then check server overlay | ||||
|         friends_allowed = False | ||||
|         owner_id = None | ||||
|         if source.allow_friends: | ||||
|             owner_api = PlexAuth(source, source.plex_token) | ||||
|             owner_id = owner_api.get_user_info | ||||
|             owner_friends = owner_api.get_friends() | ||||
|             for friend in owner_friends: | ||||
|                 if int(friend.get("id", "0")) == int(identifier): | ||||
| @ -90,16 +99,18 @@ class PlexSourceViewSet(ModelViewSet): | ||||
|                         "allowing user for plex because of friend", | ||||
|                         user=user_info["username"], | ||||
|                     ) | ||||
|         if not auth_api.check_server_overlap() or not friends_allowed: | ||||
|             LOGGER.warning( | ||||
|                 "Denying plex auth because no server overlay and no friends", | ||||
|                 user=user_info["username"], | ||||
|             ) | ||||
|             raise Http404 | ||||
|         servers_allowed = auth_api.check_server_overlap() | ||||
|         owner_allowed = owner_id == identifier | ||||
|         if any([friends_allowed, servers_allowed, owner_allowed]): | ||||
|             sfm = PlexSourceFlowManager( | ||||
|                 source=source, | ||||
|                 request=request, | ||||
|                 identifier=str(identifier), | ||||
|                 enroll_info=user_info, | ||||
|             ) | ||||
|         return sfm.get_flow(plex_token=plex_token) | ||||
|             return to_stage_response(request, sfm.get_flow(plex_token=plex_token)) | ||||
|         LOGGER.warning( | ||||
|             "Denying plex auth because no server overlay and no friends and not owner", | ||||
|             user=user_info["username"], | ||||
|         ) | ||||
|         raise PermissionDenied("Access denied.") | ||||
|  | ||||
| @ -105,8 +105,8 @@ class PlexSourceFlowManager(SourceFlowManager): | ||||
|     connection_type = PlexSourceConnection | ||||
|  | ||||
|     def update_connection( | ||||
|         self, connection: PlexSourceConnection, plex_token: str | ||||
|         self, connection: PlexSourceConnection, **kwargs | ||||
|     ) -> PlexSourceConnection: | ||||
|         """Set the access_token on the connection""" | ||||
|         connection.plex_token = plex_token | ||||
|         connection.plex_token = kwargs.get("plex_token") | ||||
|         return connection | ||||
|  | ||||
| @ -13,6 +13,8 @@ import { BaseStage } from "../../stages/base"; | ||||
| import { PlexAPIClient, popupCenterScreen } from "./API"; | ||||
| import { DEFAULT_CONFIG } from "../../../api/Config"; | ||||
| import { SourcesApi } from "authentik-api"; | ||||
| import { showMessage } from "../../../elements/messages/MessageContainer"; | ||||
| import { MessageLevel } from "../../../elements/messages/Message"; | ||||
|  | ||||
| export interface PlexAuthenticationChallenge extends Challenge { | ||||
|  | ||||
| @ -41,8 +43,18 @@ export class PlexLoginInit extends BaseStage { | ||||
|                     plexToken: token, | ||||
|                 }, | ||||
|                 slug: this.challenge?.slug || "", | ||||
|             }).then(r => { | ||||
|             }).then((r) => { | ||||
|                 window.location.assign(r.to); | ||||
|             }).catch((r: Response) => { | ||||
|                 r.json().then((body: {detail: string}) => { | ||||
|                     showMessage({ | ||||
|                         level: MessageLevel.error, | ||||
|                         message: body.detail | ||||
|                     }); | ||||
|                     setTimeout(() => { | ||||
|                         window.location.assign("/"); | ||||
|                     }, 5000); | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer