providers/oauth2: fix interactive device flow (#9076)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L
2024-03-29 15:38:49 +01:00
committed by GitHub
parent 0e82facfb4
commit 7010682122
4 changed files with 14 additions and 14 deletions

View File

@ -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())

View File

@ -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,

View File

@ -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

View File

@ -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"]