move functions to device
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
parent
91c2348b8e
commit
e99a660a5f
|
@ -5,9 +5,15 @@ from rest_framework.filters import OrderingFilter, SearchFilter
|
||||||
from rest_framework.permissions import IsAdminUser
|
from rest_framework.permissions import IsAdminUser
|
||||||
from rest_framework.serializers import ModelSerializer
|
from rest_framework.serializers import ModelSerializer
|
||||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
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.api.authorization import OwnerFilter, OwnerPermissions
|
||||||
from authentik.core.api.used_by import UsedByMixin
|
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
|
from authentik.stages.authenticator_mobile.models import MobileDevice
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,6 +44,69 @@ class MobileDeviceViewSet(
|
||||||
permission_classes = [OwnerPermissions]
|
permission_classes = [OwnerPermissions]
|
||||||
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]
|
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):
|
class AdminMobileDeviceViewSet(ModelViewSet):
|
||||||
"""Viewset for Mobile authenticator devices (for admins)"""
|
"""Viewset for Mobile authenticator devices (for admins)"""
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
"""AuthenticatorMobileStage API Views"""
|
"""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 rest_framework.viewsets import ModelViewSet
|
||||||
|
|
||||||
from authentik.core.api.used_by import UsedByMixin
|
from authentik.core.api.used_by import UsedByMixin
|
||||||
from authentik.flows.api.stages import StageSerializer
|
from authentik.flows.api.stages import StageSerializer
|
||||||
from authentik.stages.authenticator_mobile.api.auth import MobileDeviceTokenAuthentication
|
|
||||||
from authentik.stages.authenticator_mobile.models import AuthenticatorMobileStage
|
from authentik.stages.authenticator_mobile.models import AuthenticatorMobileStage
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,30 +28,3 @@ class AuthenticatorMobileStageViewSet(UsedByMixin, ModelViewSet):
|
||||||
]
|
]
|
||||||
search_fields = ["name"]
|
search_fields = ["name"]
|
||||||
ordering = ["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)
|
|
||||||
|
|
|
@ -87,3 +87,5 @@ class MobileDeviceToken(ExpiringModel):
|
||||||
device = models.ForeignKey(MobileDevice, on_delete=models.CASCADE, null=True)
|
device = models.ForeignKey(MobileDevice, on_delete=models.CASCADE, null=True)
|
||||||
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
|
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
|
||||||
token = models.TextField(default=default_token_key)
|
token = models.TextField(default=default_token_key)
|
||||||
|
|
||||||
|
firebase_token = models.TextField(blank=True)
|
||||||
|
|
|
@ -10,7 +10,7 @@ from authentik.flows.challenge import (
|
||||||
WithUserInfoChallenge,
|
WithUserInfoChallenge,
|
||||||
)
|
)
|
||||||
from authentik.flows.stage import ChallengeStageView
|
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"
|
FLOW_PLAN_MOBILE_ENROLL = "authentik/stages/authenticator_mobile/enroll"
|
||||||
|
|
||||||
|
@ -45,19 +45,23 @@ class AuthenticatorMobileStageView(ChallengeStageView):
|
||||||
"""Prepare the token"""
|
"""Prepare the token"""
|
||||||
if FLOW_PLAN_MOBILE_ENROLL in self.executor.plan.context:
|
if FLOW_PLAN_MOBILE_ENROLL in self.executor.plan.context:
|
||||||
return
|
return
|
||||||
|
device = MobileDevice.objects.create(
|
||||||
|
user=self.get_pending_user(),
|
||||||
|
stage=self.executor.current_stage,
|
||||||
|
)
|
||||||
token = MobileDeviceToken.objects.create(
|
token = MobileDeviceToken.objects.create(
|
||||||
user=self.get_pending_user(),
|
user=self.get_pending_user(),
|
||||||
|
device=device,
|
||||||
)
|
)
|
||||||
self.executor.plan.context[FLOW_PLAN_MOBILE_ENROLL] = token
|
self.executor.plan.context[FLOW_PLAN_MOBILE_ENROLL] = token
|
||||||
|
|
||||||
def get_challenge(self, *args, **kwargs) -> Challenge:
|
def get_challenge(self, *args, **kwargs) -> Challenge:
|
||||||
stage: AuthenticatorMobileStage = self.executor.current_stage
|
|
||||||
self.prepare()
|
self.prepare()
|
||||||
payload = AuthenticatorMobilePayloadChallenge(
|
payload = AuthenticatorMobilePayloadChallenge(
|
||||||
data={
|
data={
|
||||||
# TODO: use cloud gateway?
|
# TODO: use cloud gateway?
|
||||||
"u": self.request.build_absolute_uri("/"),
|
"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,
|
"t": self.executor.plan.context[FLOW_PLAN_MOBILE_ENROLL].token,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
224
schema.yml
224
schema.yml
|
@ -2157,6 +2157,123 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/GenericError'
|
$ref: '#/components/schemas/GenericError'
|
||||||
description: ''
|
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/:
|
/authenticators/mobile/{id}/used_by/:
|
||||||
get:
|
get:
|
||||||
operationId: authenticators_mobile_used_by_list
|
operationId: authenticators_mobile_used_by_list
|
||||||
|
@ -23421,47 +23538,6 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/GenericError'
|
$ref: '#/components/schemas/GenericError'
|
||||||
description: ''
|
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/:
|
/stages/authenticator/mobile/{stage_uuid}/used_by/:
|
||||||
get:
|
get:
|
||||||
operationId: stages_authenticator_mobile_used_by_list
|
operationId: stages_authenticator_mobile_used_by_list
|
||||||
|
@ -35133,16 +35209,20 @@ components:
|
||||||
properties:
|
properties:
|
||||||
device_token:
|
device_token:
|
||||||
type: string
|
type: string
|
||||||
|
device_uuid:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
required:
|
required:
|
||||||
- device_token
|
- device_token
|
||||||
|
- device_uuid
|
||||||
MobileDeviceEnrollmentRequest:
|
MobileDeviceEnrollmentRequest:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
device_token:
|
token:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
required:
|
required:
|
||||||
- device_token
|
- token
|
||||||
MobileDeviceRequest:
|
MobileDeviceRequest:
|
||||||
type: object
|
type: object
|
||||||
description: Serializer for Mobile authenticator devices
|
description: Serializer for Mobile authenticator devices
|
||||||
|
@ -35154,6 +35234,14 @@ components:
|
||||||
maxLength: 64
|
maxLength: 64
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
|
MobileDeviceSetPushKeyRequest:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
firebase_key:
|
||||||
|
type: string
|
||||||
|
minLength: 1
|
||||||
|
required:
|
||||||
|
- firebase_key
|
||||||
ModelEnum:
|
ModelEnum:
|
||||||
enum:
|
enum:
|
||||||
- authentik_crypto.certificatekeypair
|
- authentik_crypto.certificatekeypair
|
||||||
|
@ -36361,30 +36449,7 @@ components:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
pagination:
|
pagination:
|
||||||
type: object
|
$ref: '#/components/schemas/Pagination'
|
||||||
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
|
|
||||||
results:
|
results:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
|
@ -36792,30 +36857,7 @@ components:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
pagination:
|
pagination:
|
||||||
type: object
|
$ref: '#/components/schemas/Pagination'
|
||||||
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
|
|
||||||
results:
|
results:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
|
|
Reference in New Issue