authentik.providers.oauth2.views.device_finish

Device flow finish stage

 1"""Device flow finish stage"""
 2
 3from django.http import HttpResponse
 4from rest_framework.fields import CharField
 5
 6from authentik.flows.challenge import Challenge, ChallengeResponse
 7from authentik.flows.planner import FlowPlan
 8from authentik.flows.stage import ChallengeStageView
 9from authentik.flows.views.executor import SESSION_KEY_PLAN
10from authentik.providers.oauth2.models import DeviceToken
11
12PLAN_CONTEXT_DEVICE = "goauthentik.io/providers/oauth2/device"
13
14
15class OAuthDeviceCodeFinishChallenge(Challenge):
16    """Final challenge after user enters their code"""
17
18    component = CharField(default="ak-provider-oauth2-device-code-finish")
19
20
21class OAuthDeviceCodeFinishChallengeResponse(ChallengeResponse):
22    """Response that device has been authenticated and tab can be closed"""
23
24    component = CharField(default="ak-provider-oauth2-device-code-finish")
25
26
27class OAuthDeviceCodeFinishStage(ChallengeStageView):
28    """Stage to finish the OAuth device code flow"""
29
30    response_class = OAuthDeviceCodeFinishChallengeResponse
31
32    def get_challenge(self, *args, **kwargs) -> Challenge:
33        plan: FlowPlan = self.request.session[SESSION_KEY_PLAN]
34        token: DeviceToken = plan.context[PLAN_CONTEXT_DEVICE]
35        # As we're required to be authenticated by now, we can rely on
36        # request.user
37        token.user = self.request.user
38        token.save()
39        return OAuthDeviceCodeFinishChallenge(
40            data={
41                "component": "ak-provider-oauth2-device-code-finish",
42            }
43        )
44
45    def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
46        self.executor.stage_ok()
PLAN_CONTEXT_DEVICE = 'goauthentik.io/providers/oauth2/device'
class OAuthDeviceCodeFinishChallenge(authentik.flows.challenge.Challenge):
16class OAuthDeviceCodeFinishChallenge(Challenge):
17    """Final challenge after user enters their code"""
18
19    component = CharField(default="ak-provider-oauth2-device-code-finish")

Final challenge after user enters their code

component
class OAuthDeviceCodeFinishChallengeResponse(authentik.flows.challenge.ChallengeResponse):
22class OAuthDeviceCodeFinishChallengeResponse(ChallengeResponse):
23    """Response that device has been authenticated and tab can be closed"""
24
25    component = CharField(default="ak-provider-oauth2-device-code-finish")

Response that device has been authenticated and tab can be closed

component
class OAuthDeviceCodeFinishStage(authentik.flows.stage.ChallengeStageView):
28class OAuthDeviceCodeFinishStage(ChallengeStageView):
29    """Stage to finish the OAuth device code flow"""
30
31    response_class = OAuthDeviceCodeFinishChallengeResponse
32
33    def get_challenge(self, *args, **kwargs) -> Challenge:
34        plan: FlowPlan = self.request.session[SESSION_KEY_PLAN]
35        token: DeviceToken = plan.context[PLAN_CONTEXT_DEVICE]
36        # As we're required to be authenticated by now, we can rely on
37        # request.user
38        token.user = self.request.user
39        token.save()
40        return OAuthDeviceCodeFinishChallenge(
41            data={
42                "component": "ak-provider-oauth2-device-code-finish",
43            }
44        )
45
46    def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
47        self.executor.stage_ok()

Stage to finish the OAuth device code flow

response_class = <class 'OAuthDeviceCodeFinishChallengeResponse'>
def get_challenge(self, *args, **kwargs) -> authentik.flows.challenge.Challenge:
33    def get_challenge(self, *args, **kwargs) -> Challenge:
34        plan: FlowPlan = self.request.session[SESSION_KEY_PLAN]
35        token: DeviceToken = plan.context[PLAN_CONTEXT_DEVICE]
36        # As we're required to be authenticated by now, we can rely on
37        # request.user
38        token.user = self.request.user
39        token.save()
40        return OAuthDeviceCodeFinishChallenge(
41            data={
42                "component": "ak-provider-oauth2-device-code-finish",
43            }
44        )

Return the challenge that the client should solve

def challenge_valid( self, response: authentik.flows.challenge.ChallengeResponse) -> django.http.response.HttpResponse:
46    def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
47        self.executor.stage_ok()

Callback when the challenge has the correct format