move functions to device

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer 2023-09-03 00:00:16 +02:00
parent 91c2348b8e
commit e99a660a5f
No known key found for this signature in database
5 changed files with 211 additions and 127 deletions

View File

@ -5,9 +5,15 @@ from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from drf_spectacular.utils import extend_schema, inline_serializer
from rest_framework.decorators import action
from rest_framework.fields import CharField, UUIDField
from rest_framework.request import Request
from rest_framework.response import Response
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.core.api.used_by import UsedByMixin
from authentik.stages.authenticator_mobile.api.auth import MobileDeviceTokenAuthentication
from authentik.stages.authenticator_mobile.models import MobileDevice
@ -38,6 +44,69 @@ class MobileDeviceViewSet(
permission_classes = [OwnerPermissions]
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]
@extend_schema(
responses={
204: "",
},
request=inline_serializer(
"MobileDeviceSetPushKeySerializer",
{
"firebase_key": CharField(required=True),
},
),
)
@action(
methods=["POST"],
detail=True,
permission_classes=[],
authentication_classes=[MobileDeviceTokenAuthentication],
)
def set_notification_key(self):
"""Called by the phone whenever the firebase key changes and we need to update it"""
device = self.get_object()
print(self.request.user)
@action(
methods=["POST"],
detail=True,
permission_classes=[],
authentication_classes=[MobileDeviceTokenAuthentication],
)
def receive_response():
"""Get response from notification on phone"""
pass
@extend_schema(
responses={
200: inline_serializer(
"MobileDeviceEnrollmentCallbackSerializer",
{
"device_token": CharField(required=True),
"device_uuid": UUIDField(required=True)
},
),
},
request=inline_serializer(
"MobileDeviceEnrollmentSerializer",
{
# New API token (that will be rotated at some point)
# also used by the backend to sign requests to the cloud broker
# also used by the app to check the signature of incoming requests
"token": CharField(required=True),
},
),
)
@action(
methods=["POST"],
detail=True,
permission_classes=[],
authentication_classes=[MobileDeviceTokenAuthentication],
)
def enrollment_callback(self, request: Request, pk: str) -> Response:
"""Enrollment callback"""
print(request.data)
return Response(status=204)
class AdminMobileDeviceViewSet(ModelViewSet):
"""Viewset for Mobile authenticator devices (for admins)"""

View File

@ -1,14 +1,8 @@
"""AuthenticatorMobileStage API Views"""
from drf_spectacular.utils import extend_schema, inline_serializer
from rest_framework.decorators import action
from rest_framework.fields import CharField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.flows.api.stages import StageSerializer
from authentik.stages.authenticator_mobile.api.auth import MobileDeviceTokenAuthentication
from authentik.stages.authenticator_mobile.models import AuthenticatorMobileStage
@ -34,30 +28,3 @@ class AuthenticatorMobileStageViewSet(UsedByMixin, ModelViewSet):
]
search_fields = ["name"]
ordering = ["name"]
@extend_schema(
responses={
200: inline_serializer(
"MobileDeviceEnrollmentCallbackSerializer",
{
"device_token": CharField(required=True),
},
),
},
request=inline_serializer(
"MobileDeviceEnrollmentSerializer",
{
"device_token": CharField(required=True),
},
),
)
@action(
methods=["POST"],
detail=True,
permission_classes=[],
authentication_classes=[MobileDeviceTokenAuthentication],
)
def enrollment_callback(self, request: Request, pk: str) -> Response:
"""Enrollment callback"""
print(request.data)
return Response(status=204)

View File

@ -87,3 +87,5 @@ class MobileDeviceToken(ExpiringModel):
device = models.ForeignKey(MobileDevice, on_delete=models.CASCADE, null=True)
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
token = models.TextField(default=default_token_key)
firebase_token = models.TextField(blank=True)

View File

@ -10,7 +10,7 @@ from authentik.flows.challenge import (
WithUserInfoChallenge,
)
from authentik.flows.stage import ChallengeStageView
from authentik.stages.authenticator_mobile.models import AuthenticatorMobileStage, MobileDeviceToken
from authentik.stages.authenticator_mobile.models import AuthenticatorMobileStage, MobileDevice, MobileDeviceToken
FLOW_PLAN_MOBILE_ENROLL = "authentik/stages/authenticator_mobile/enroll"
@ -45,19 +45,23 @@ class AuthenticatorMobileStageView(ChallengeStageView):
"""Prepare the token"""
if FLOW_PLAN_MOBILE_ENROLL in self.executor.plan.context:
return
device = MobileDevice.objects.create(
user=self.get_pending_user(),
stage=self.executor.current_stage,
)
token = MobileDeviceToken.objects.create(
user=self.get_pending_user(),
device=device,
)
self.executor.plan.context[FLOW_PLAN_MOBILE_ENROLL] = token
def get_challenge(self, *args, **kwargs) -> Challenge:
stage: AuthenticatorMobileStage = self.executor.current_stage
self.prepare()
payload = AuthenticatorMobilePayloadChallenge(
data={
# TODO: use cloud gateway?
"u": self.request.build_absolute_uri("/"),
"s": str(stage.stage_uuid),
"s": self.executor.plan.context[FLOW_PLAN_MOBILE_ENROLL].device.pk,
"t": self.executor.plan.context[FLOW_PLAN_MOBILE_ENROLL].token,
}
)

View File

@ -2157,6 +2157,123 @@ paths:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/authenticators/mobile/{id}/enrollment_callback/:
post:
operationId: authenticators_mobile_enrollment_callback_create
description: Enrollment callback
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Mobile Device.
required: true
tags:
- authenticators
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/MobileDeviceEnrollmentRequest'
required: true
security:
- mobile_device_token: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/MobileDeviceEnrollmentCallback'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/authenticators/mobile/{id}/receive_response/:
post:
operationId: authenticators_mobile_receive_response_create
description: Get response from notification on phone
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Mobile Device.
required: true
tags:
- authenticators
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/MobileDeviceRequest'
required: true
security:
- mobile_device_token: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/MobileDevice'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/authenticators/mobile/{id}/set_notification_key/:
post:
operationId: authenticators_mobile_set_notification_key_create
description: Called by the phone whenever the firebase key changes and we need
to update it
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Mobile Device.
required: true
tags:
- authenticators
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/MobileDeviceSetPushKeyRequest'
required: true
security:
- mobile_device_token: []
responses:
'204':
description: No response body
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/authenticators/mobile/{id}/used_by/:
get:
operationId: authenticators_mobile_used_by_list
@ -23421,47 +23538,6 @@ paths:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/stages/authenticator/mobile/{stage_uuid}/enrollment_callback/:
post:
operationId: stages_authenticator_mobile_enrollment_callback_create
description: Enrollment callback
parameters:
- in: path
name: stage_uuid
schema:
type: string
format: uuid
description: A UUID string identifying this Mobile Authenticator Setup Stage.
required: true
tags:
- stages
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/MobileDeviceEnrollmentRequest'
required: true
security:
- mobile_device_token: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/MobileDeviceEnrollmentCallback'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/stages/authenticator/mobile/{stage_uuid}/used_by/:
get:
operationId: stages_authenticator_mobile_used_by_list
@ -35133,16 +35209,20 @@ components:
properties:
device_token:
type: string
device_uuid:
type: string
format: uuid
required:
- device_token
- device_uuid
MobileDeviceEnrollmentRequest:
type: object
properties:
device_token:
token:
type: string
minLength: 1
required:
- device_token
- token
MobileDeviceRequest:
type: object
description: Serializer for Mobile authenticator devices
@ -35154,6 +35234,14 @@ components:
maxLength: 64
required:
- name
MobileDeviceSetPushKeyRequest:
type: object
properties:
firebase_key:
type: string
minLength: 1
required:
- firebase_key
ModelEnum:
enum:
- authentik_crypto.certificatekeypair
@ -36361,30 +36449,7 @@ components:
type: object
properties:
pagination:
type: object
properties:
next:
type: number
previous:
type: number
count:
type: number
current:
type: number
total_pages:
type: number
start_index:
type: number
end_index:
type: number
required:
- next
- previous
- count
- current
- total_pages
- start_index
- end_index
$ref: '#/components/schemas/Pagination'
results:
type: array
items:
@ -36792,30 +36857,7 @@ components:
type: object
properties:
pagination:
type: object
properties:
next:
type: number
previous:
type: number
count:
type: number
current:
type: number
total_pages:
type: number
start_index:
type: number
end_index:
type: number
required:
- next
- previous
- count
- current
- total_pages
- start_index
- end_index
$ref: '#/components/schemas/Pagination'
results:
type: array
items: