providers/oauth2: fix interactive device flow (#9076)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
@ -59,11 +59,11 @@ class FlowPlan:
|
||||
markers: list[StageMarker] = field(default_factory=list)
|
||||
|
||||
def append_stage(self, stage: Stage, marker: StageMarker | None = None):
|
||||
"""Append `stage` to all stages, optionally with stage marker"""
|
||||
"""Append `stage` to the end of the plan, optionally with stage marker"""
|
||||
return self.append(FlowStageBinding(stage=stage), marker)
|
||||
|
||||
def append(self, binding: FlowStageBinding, marker: StageMarker | None = None):
|
||||
"""Append `stage` to all stages, optionally with stage marker"""
|
||||
"""Append `stage` to the end of the plan, optionally with stage marker"""
|
||||
self.bindings.append(binding)
|
||||
self.markers.append(marker or StageMarker())
|
||||
|
||||
|
||||
@ -450,7 +450,7 @@ class FlowExecutorView(APIView):
|
||||
return to_stage_response(self.request, challenge_view.get(self.request))
|
||||
|
||||
def cancel(self):
|
||||
"""Cancel current execution and return a redirect"""
|
||||
"""Cancel current flow execution"""
|
||||
keys_to_delete = [
|
||||
SESSION_KEY_APPLICATION_PRE,
|
||||
SESSION_KEY_PLAN,
|
||||
|
||||
@ -25,7 +25,7 @@ class OAuthDeviceCodeFinishChallengeResponse(ChallengeResponse):
|
||||
|
||||
|
||||
class OAuthDeviceCodeFinishStage(ChallengeStageView):
|
||||
"""Stage show at the end of a device flow"""
|
||||
"""Stage to finish the OAuth device code flow"""
|
||||
|
||||
response_class = OAuthDeviceCodeFinishChallengeResponse
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views import View
|
||||
from rest_framework.exceptions import ErrorDetail
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.fields import CharField, IntegerField
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
@ -57,6 +57,7 @@ def validate_code(code: int, request: HttpRequest) -> HttpResponse | None:
|
||||
scope_descriptions = UserInfoView().get_scope_descriptions(token.scope, token.provider)
|
||||
planner = FlowPlanner(token.provider.authorization_flow)
|
||||
planner.allow_empty_flows = True
|
||||
planner.use_cache = False
|
||||
try:
|
||||
plan = planner.plan(
|
||||
request,
|
||||
@ -128,6 +129,13 @@ class OAuthDeviceCodeChallengeResponse(ChallengeResponse):
|
||||
code = IntegerField()
|
||||
component = CharField(default="ak-provider-oauth2-device-code")
|
||||
|
||||
def validate_code(self, code: int) -> HttpResponse | None:
|
||||
"""Validate code and save the returned http response"""
|
||||
response = validate_code(code, self.stage.request)
|
||||
if not response:
|
||||
raise ValidationError("Invalid code", "invalid")
|
||||
return response
|
||||
|
||||
|
||||
class OAuthDeviceCodeStage(ChallengeStageView):
|
||||
"""Flow challenge for users to enter device codes"""
|
||||
@ -143,12 +151,4 @@ class OAuthDeviceCodeStage(ChallengeStageView):
|
||||
)
|
||||
|
||||
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
|
||||
code = response.validated_data["code"]
|
||||
validation = validate_code(code, self.request)
|
||||
if not validation:
|
||||
response._errors.setdefault("code", [])
|
||||
response._errors["code"].append(ErrorDetail(_("Invalid code"), "invalid"))
|
||||
return self.challenge_invalid(response)
|
||||
# Run cancel to cleanup the current flow
|
||||
self.executor.cancel()
|
||||
return validation
|
||||
return response.validated_data["code"]
|
||||
|
||||
Reference in New Issue
Block a user