zou 0.20.82__py3-none-any.whl → 0.20.83__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,7 +29,7 @@ from zou.app.services import (
29
29
  persons_service,
30
30
  auth_service,
31
31
  events_service,
32
- templates_service
32
+ templates_service,
33
33
  )
34
34
 
35
35
  from zou.app.utils.flask import is_from_browser
@@ -58,20 +58,15 @@ from zou.app.services.exception import (
58
58
 
59
59
 
60
60
  class AuthenticatedResource(Resource):
61
- """
62
- Returns information if the user is authenticated else it returns a 401
63
- response.
64
- It can be used by third party tools, especially browser frontend, to know
65
- if current user is still logged in.
66
- """
67
61
 
68
62
  @jwt_required()
69
63
  def get(self):
70
64
  """
71
- Returns information if the user is authenticated else it returns a 401
72
- response.
65
+ Check authentication status
73
66
  ---
74
- description: It can be used by third party tools, especially browser frontend, to know if current user is still logged in.
67
+ description: Returns information if the user is authenticated.
68
+ It can be used by third party tools, especially browser frontend,
69
+ to know if current user is still logged in.
75
70
  tags:
76
71
  - Authentication
77
72
  responses:
@@ -92,25 +87,19 @@ class AuthenticatedResource(Resource):
92
87
 
93
88
 
94
89
  class LogoutResource(Resource):
95
- """
96
- Log user out by revoking his auth tokens. Once log out, current user
97
- cannot access to API anymore.
98
- """
99
90
 
100
91
  @jwt_required()
101
92
  @permissions.require_person
102
93
  def get(self):
103
94
  """
104
- Log user out by revoking his auth tokens.
95
+ Logout user
105
96
  ---
106
- description: Once logged out, current user cannot access the API anymore.
97
+ description: Log user out by revoking auth tokens. Once logged out, current user cannot access the API anymore.
107
98
  tags:
108
99
  - Authentication
109
100
  responses:
110
101
  200:
111
102
  description: Logout successful
112
- 500:
113
- description: Access token not found
114
103
  """
115
104
  try:
116
105
  auth_service.logout(get_jwt()["jti"])
@@ -131,49 +120,61 @@ class LogoutResource(Resource):
131
120
 
132
121
 
133
122
  class LoginResource(Resource, ArgsMixin):
134
- """
135
- Log in user by creating and registering auth tokens. Login is based
136
- on email and password. If no user match given email and a destkop ID,
137
- it looks in matching the desktop ID with the one stored in database. It is
138
- useful for clients that run on desktop tools and that don't know user
139
- email.
140
- """
141
123
 
142
124
  def post(self):
143
125
  """
144
- Log in user by creating and registering auth tokens.
126
+ Login user
145
127
  ---
146
- description: Login is based on email and password.
147
- If no user match given email and a destkop ID, it looks in matching the desktop ID with the one stored in database.
148
- It is useful for clients that run on desktop tools and that don't know user email.
128
+ description: Log in user by creating and registering auth tokens.
129
+ Login is based on email and password. If no user matches given email
130
+ It fallbacks to a desktop ID. It is useful for desktop tools that
131
+ don't know user email.
132
+ It is also possible to login with TOTP, Email OTP, FIDO and recovery
133
+ code.
149
134
  tags:
150
135
  - Authentication
151
- parameters:
152
- - in: formData
153
- name: email
154
- required: True
155
- type: string
156
- format: email
157
- example: admin@example.com
158
- - in: formData
159
- name: password
160
- required: True
161
- type: string
162
- format: password
163
- example: mysecretpassword
164
- - in: formData
165
- name: otp
166
- required: False
167
- type: string
168
- format: password
169
- example: 123456
136
+ requestBody:
137
+ required: true
138
+ content:
139
+ application/json:
140
+ schema:
141
+ type: object
142
+ properties:
143
+ email:
144
+ type: string
145
+ format: email
146
+ example: admin@example.com
147
+ description: User email address
148
+ password:
149
+ type: string
150
+ format: password
151
+ example: mysecretpassword
152
+ description: User password
153
+ required: true
154
+ totp:
155
+ type: string
156
+ example: 123456
157
+ description: TOTP verification code for two-factor authentication
158
+ required: false
159
+ email_otp:
160
+ type: string
161
+ example: 123456
162
+ description: Email OTP verification code for two-factor authentication
163
+ fido_authentication_response:
164
+ type: object
165
+ description: FIDO authentication response for WebAuth
166
+ recovery_code:
167
+ type: string
168
+ example: ABCD-EFGH-IJKL-MNOP
169
+ description: Recovery code for two-factor authentication
170
+ required:
171
+ - email
172
+ - password
170
173
  responses:
171
174
  200:
172
175
  description: Login successful
173
176
  400:
174
177
  description: Login failed
175
- 500:
176
- description: Database not reachable
177
178
  """
178
179
  (
179
180
  email,
@@ -372,9 +373,10 @@ class RefreshTokenResource(Resource):
372
373
  @permissions.require_person
373
374
  def get(self):
374
375
  """
375
- Tokens are considered as outdated every two weeks.
376
+ Refresh access token
376
377
  ---
377
- description: This route allows to make their lifetime long before they get outdated.
378
+ description: Tokens are considered outdated every two weeks.
379
+ This route allows to extend their lifetime before they get outdated.
378
380
  tags:
379
381
  - Authentication
380
382
  responses:
@@ -403,35 +405,43 @@ class RegistrationResource(Resource, ArgsMixin):
403
405
 
404
406
  def post(self):
405
407
  """
406
- Allow a user to register himself to the service.
408
+ Register new user
407
409
  ---
410
+ description: Allow a user to register himself to the service.
408
411
  tags:
409
412
  - Authentication
410
- parameters:
411
- - in: formData
412
- name: email
413
- required: True
414
- type: string
415
- format: email
416
- example: admin@example.com
417
- - in: formData
418
- name: password
419
- required: True
420
- type: string
421
- format: password
422
- - in: formData
423
- name: password_2
424
- required: True
425
- type: string
426
- format: password
427
- - in: formData
428
- name: first_name
429
- required: True
430
- type: string
431
- - in: formData
432
- name: last_name
433
- required: True
434
- type: string
413
+ requestBody:
414
+ required: true
415
+ content:
416
+ application/json:
417
+ schema:
418
+ type: object
419
+ properties:
420
+ email:
421
+ type: string
422
+ format: email
423
+ example: admin@example.com
424
+ description: User email address
425
+ password:
426
+ type: string
427
+ format: password
428
+ description: User password
429
+ password_2:
430
+ type: string
431
+ format: password
432
+ description: Password confirmation
433
+ first_name:
434
+ type: string
435
+ description: User first name
436
+ last_name:
437
+ type: string
438
+ description: User last name
439
+ required:
440
+ - email
441
+ - password
442
+ - password_2
443
+ - first_name
444
+ - last_name
435
445
  responses:
436
446
  201:
437
447
  description: Registration successful
@@ -508,42 +518,41 @@ class RegistrationResource(Resource, ArgsMixin):
508
518
 
509
519
 
510
520
  class ChangePasswordResource(Resource, ArgsMixin):
511
- """
512
- Allow the user to change his password. Prior to modify the password,
513
- it requires to give the current password (to make sure the user changing
514
- the password is not someone who stealed the session).
515
- The new password requires a confirmation to ensure that the user didn't
516
- make mistake by typing his new password.
517
- """
518
521
 
519
522
  @jwt_required()
520
523
  @permissions.require_person
521
524
  def post(self):
522
525
  """
523
- Allow the user to change his password.
526
+ Change user password
524
527
  ---
525
- description: Prior to modifying the password, it requires to give the current password
526
- (to make sure the user changing the password is not someone who stealed the session).
527
- The new password requires a confirmation to ensure that the user didn't
528
- make a mistake by typing his new password.
528
+ description: Allow the user to change his password. Requires current
529
+ password for verification and password confirmation to ensure
530
+ accuracy.
529
531
  tags:
530
532
  - Authentication
531
- parameters:
532
- - in: formData
533
- name: old_password
534
- required: True
535
- type: string
536
- format: password
537
- - in: formData
538
- name: password
539
- required: True
540
- type: string
541
- format: password
542
- - in: formData
543
- name: password_2
544
- required: True
545
- type: string
546
- format: password
533
+ requestBody:
534
+ required: true
535
+ content:
536
+ application/json:
537
+ schema:
538
+ type: object
539
+ properties:
540
+ old_password:
541
+ type: string
542
+ format: password
543
+ description: Current password
544
+ password:
545
+ type: string
546
+ format: password
547
+ description: New password
548
+ password_2:
549
+ type: string
550
+ format: password
551
+ description: New password confirmation
552
+ required:
553
+ - old_password
554
+ - password
555
+ - password_2
547
556
  responses:
548
557
  200:
549
558
  description: Password changed
@@ -625,42 +634,45 @@ Your IP when you have changed your password is: {person_IP}.
625
634
 
626
635
 
627
636
  class ResetPasswordResource(Resource, ArgsMixin):
628
- """
629
- Resource to allow a user to change his password when he forgets it.
630
- It uses a classic scheme: a token is sent by email to the user. Then
631
- he can change his password.
632
- """
633
637
 
634
638
  def put(self):
635
639
  """
636
- Resource to allow a user to change his password when he forgets it.
640
+ Reset password with token
637
641
  ---
638
- description: "It uses a classic scheme: a token is sent by email to the user.
639
- Then he can change his password."
642
+ description: Allow a user to change his password when he forgets it.
643
+ It uses a token sent by email to the user to verify it is the user
644
+ who requested the password reset.
640
645
  tags:
641
646
  - Authentication
642
- parameters:
643
- - in: formData
644
- name: email
645
- required: True
646
- type: string
647
- format: email
648
- example: admin@example.com
649
- - in: formData
650
- name: token
651
- required: True
652
- type: string
653
- format: JWT token
654
- - in: formData
655
- name: password
656
- required: True
657
- type: string
658
- format: password
659
- - in: formData
660
- name: password2
661
- required: True
662
- type: string
663
- format: password
647
+ requestBody:
648
+ required: true
649
+ content:
650
+ application/json:
651
+ schema:
652
+ type: object
653
+ properties:
654
+ email:
655
+ type: string
656
+ format: email
657
+ example: admin@example.com
658
+ description: User email address
659
+ token:
660
+ type: string
661
+ format: JWT token
662
+ description: Password reset token
663
+ password:
664
+ type: string
665
+ format: password
666
+ description: New password
667
+ password2:
668
+ type: string
669
+ format: password
670
+ description: New password confirmation
671
+ required:
672
+ - email
673
+ - token
674
+ - password
675
+ - password2
664
676
  responses:
665
677
  200:
666
678
  description: Password reset
@@ -712,19 +724,26 @@ class ResetPasswordResource(Resource, ArgsMixin):
712
724
 
713
725
  def post(self):
714
726
  """
715
- Resource to allow a user to change his password when he forgets it.
727
+ Request password reset
716
728
  ---
717
- description: "It uses a classic scheme: a token is sent by email to the user.
718
- Then he can change his password."
729
+ description: Send a password reset token by email to the user.
730
+ It uses a classic scheme where a token is sent by email.
719
731
  tags:
720
732
  - Authentication
721
- parameters:
722
- - in: formData
723
- name: email
724
- required: True
725
- type: string
726
- format: email
727
- example: admin@example.com
733
+ requestBody:
734
+ required: true
735
+ content:
736
+ application/json:
737
+ schema:
738
+ type: object
739
+ properties:
740
+ email:
741
+ type: string
742
+ format: email
743
+ example: admin@example.com
744
+ description: User email address
745
+ required:
746
+ - email
728
747
  responses:
729
748
  200:
730
749
  description: Reset token sent
@@ -789,26 +808,22 @@ The IP of the person who requested this is: {person_IP}.
789
808
 
790
809
 
791
810
  class TOTPResource(Resource, ArgsMixin):
792
- """
793
- Resource to allow a user to enable/disable TOTP.
794
- """
795
811
 
796
812
  @jwt_required()
797
813
  @permissions.require_person
798
814
  def put(self):
799
815
  """
800
- Resource to allow a user to pre-enable TOTP.
816
+ Pre-enable TOTP
801
817
  ---
802
- description: ""
818
+ description: Prepare TOTP (Time-based One-Time Password) for enabling.
819
+ It returns provisioning URI and secret for authenticator app setup.
803
820
  tags:
804
821
  - Authentication
805
822
  responses:
806
823
  200:
807
- description: TOTP enabled
824
+ description: TOTP pre-enabled
808
825
  400:
809
- description: Invalid password
810
- Wrong or expired token
811
- Inactive user
826
+ description: TOTP already enabled
812
827
  """
813
828
  try:
814
829
  totp_provisionning_uri, totp_secret = auth_service.pre_enable_totp(
@@ -828,18 +843,29 @@ class TOTPResource(Resource, ArgsMixin):
828
843
  @permissions.require_person
829
844
  def post(self):
830
845
  """
831
- Resource to allow a user to enable TOTP.
846
+ Enable TOTP
832
847
  ---
833
- description: ""
848
+ description: Enable TOTP (Time-based One-Time Password) authentication.
849
+ It requires verification code from authenticator app.
834
850
  tags:
835
851
  - Authentication
852
+ requestBody:
853
+ required: true
854
+ content:
855
+ application/json:
856
+ schema:
857
+ type: object
858
+ properties:
859
+ totp:
860
+ type: string
861
+ description: TOTP verification code from authenticator app
862
+ required:
863
+ - totp
836
864
  responses:
837
865
  200:
838
866
  description: TOTP enabled
839
867
  400:
840
- description: Invalid password
841
- Wrong or expired token
842
- Inactive user
868
+ description: TOTP already enabled or verification failed
843
869
  """
844
870
  args = self.get_args([("totp", "", True)])
845
871
 
@@ -867,16 +893,36 @@ class TOTPResource(Resource, ArgsMixin):
867
893
  @permissions.require_person
868
894
  def delete(self):
869
895
  """
870
- Resource to allow a user to disable TOTP.
896
+ Disable TOTP
871
897
  ---
872
- description: ""
898
+ description: Disable TOTP (Time-based One-Time Password) authentication.
899
+ It requires two-factor authentication verification.
873
900
  tags:
874
901
  - Authentication
902
+ requestBody:
903
+ required: true
904
+ content:
905
+ application/json:
906
+ schema:
907
+ type: object
908
+ properties:
909
+ totp:
910
+ type: string
911
+ description: TOTP verification code
912
+ email_otp:
913
+ type: string
914
+ description: Email OTP verification code
915
+ fido_authentication_response:
916
+ type: object
917
+ description: FIDO authentication response
918
+ recovery_code:
919
+ type: string
920
+ description: Recovery code for two-factor authentication
875
921
  responses:
876
922
  200:
877
923
  description: TOTP disabled
878
924
  400:
879
- description: TOTP not enabled
925
+ description: TOTP not enabled or verification failed
880
926
  """
881
927
  args = self.get_args(
882
928
  [
@@ -920,25 +966,27 @@ class TOTPResource(Resource, ArgsMixin):
920
966
 
921
967
 
922
968
  class EmailOTPResource(Resource, ArgsMixin):
923
- """
924
- Resource to allow a user to enable/disable OTP by email or to send an OTP
925
- by email.
926
- """
927
969
 
928
970
  def get(self):
929
971
  """
930
- Resource to send an OTP by email to user.
972
+ Send email OTP
931
973
  ---
932
- description: ""
974
+ description: Send a one-time password by email to the user for
975
+ authentication.
933
976
  tags:
934
977
  - Authentication
978
+ parameters:
979
+ - in: query
980
+ name: email
981
+ required: True
982
+ type: string
983
+ format: email
984
+ description: User email address
935
985
  responses:
936
986
  200:
937
987
  description: OTP by email sent
938
988
  400:
939
- description: Invalid password
940
- Wrong or expired token
941
- Inactive user
989
+ description: OTP by email not enabled
942
990
  """
943
991
  args = self.get_args(
944
992
  [
@@ -973,18 +1021,17 @@ class EmailOTPResource(Resource, ArgsMixin):
973
1021
  @permissions.require_person
974
1022
  def put(self):
975
1023
  """
976
- Resource to allow a user to pre-enable OTP by email.
1024
+ Pre-enable email OTP
977
1025
  ---
978
- description: ""
1026
+ description: Prepare email OTP (One-Time Password) for enabling.
1027
+ It sets up email-based two-factor authentication.
979
1028
  tags:
980
1029
  - Authentication
981
1030
  responses:
982
1031
  200:
983
- description: OTP by email enabled
1032
+ description: Email OTP pre-enabled
984
1033
  400:
985
- description: Invalid password
986
- Wrong or expired token
987
- Inactive user
1034
+ description: Email OTP already enabled
988
1035
  """
989
1036
  try:
990
1037
  auth_service.pre_enable_email_otp(
@@ -1001,18 +1048,29 @@ class EmailOTPResource(Resource, ArgsMixin):
1001
1048
  @permissions.require_person
1002
1049
  def post(self):
1003
1050
  """
1004
- Resource to allow a user to enable OTP by email.
1051
+ Enable email OTP
1005
1052
  ---
1006
- description: ""
1053
+ description: Enable email OTP (One-Time Password) authentication.
1054
+ It requires verification code sent to email.
1007
1055
  tags:
1008
1056
  - Authentication
1057
+ requestBody:
1058
+ required: true
1059
+ content:
1060
+ application/json:
1061
+ schema:
1062
+ type: object
1063
+ properties:
1064
+ email_otp:
1065
+ type: string
1066
+ description: Email OTP verification code
1067
+ required:
1068
+ - email_otp
1009
1069
  responses:
1010
1070
  200:
1011
- description: OTP by email enabled
1071
+ description: Email OTP enabled
1012
1072
  400:
1013
- description: Invalid password
1014
- Wrong or expired token
1015
- Inactive user
1073
+ description: Email OTP already enabled or verification failed
1016
1074
  """
1017
1075
  args = self.get_args([("email_otp", "", True)])
1018
1076
 
@@ -1041,19 +1099,36 @@ class EmailOTPResource(Resource, ArgsMixin):
1041
1099
  @permissions.require_person
1042
1100
  def delete(self):
1043
1101
  """
1044
- Resource to allow a user to disable OTP by email.
1102
+ Disable email OTP
1045
1103
  ---
1046
- description: ""
1104
+ description: Disable email OTP (One-Time Password) authentication.
1105
+ It requires two-factor authentication verification.
1047
1106
  tags:
1048
1107
  - Authentication
1108
+ requestBody:
1109
+ required: true
1110
+ content:
1111
+ application/json:
1112
+ schema:
1113
+ type: object
1114
+ properties:
1115
+ totp:
1116
+ type: string
1117
+ description: TOTP verification code
1118
+ email_otp:
1119
+ type: string
1120
+ description: Email OTP verification code
1121
+ fido_authentication_response:
1122
+ type: object
1123
+ description: FIDO authentication response
1124
+ recovery_code:
1125
+ type: string
1126
+ description: Recovery code for two-factor authentication
1049
1127
  responses:
1050
1128
  200:
1051
- description: OTP by email disabled.
1129
+ description: Email OTP disabled
1052
1130
  400:
1053
- description: Invalid password.
1054
- Wrong or expired token.
1055
- Inactive user.
1056
- Wrong 2FA.
1131
+ description: Email OTP not enabled or verification failed
1057
1132
  """
1058
1133
  args = self.get_args(
1059
1134
  [
@@ -1104,16 +1179,24 @@ class FIDOResource(Resource, ArgsMixin):
1104
1179
 
1105
1180
  def get(self):
1106
1181
  """
1107
- Resource to get a challenge for a FIDO device.
1182
+ Get FIDO challenge
1108
1183
  ---
1109
- description: ""
1184
+ description: Get a challenge for FIDO device authentication.
1185
+ It is used for WebAuthn authentication flow.
1110
1186
  tags:
1111
1187
  - Authentication
1188
+ parameters:
1189
+ - in: query
1190
+ name: email
1191
+ required: True
1192
+ type: string
1193
+ format: email
1194
+ description: User email address
1112
1195
  responses:
1113
1196
  200:
1114
- description: Challenge for FIDO device.
1197
+ description: FIDO challenge generated
1115
1198
  400:
1116
- description: Wrong parameter.
1199
+ description: FIDO not enabled
1117
1200
  """
1118
1201
  args = self.get_args(
1119
1202
  [
@@ -1147,18 +1230,17 @@ class FIDOResource(Resource, ArgsMixin):
1147
1230
  @permissions.require_person
1148
1231
  def put(self):
1149
1232
  """
1150
- Resource to allow a user to pre-register a FIDO device.
1233
+ Pre-register FIDO device
1151
1234
  ---
1152
- description: ""
1235
+ description: Prepare FIDO device for registration.
1236
+ It returns registration options for WebAuthn.
1153
1237
  tags:
1154
1238
  - Authentication
1155
1239
  responses:
1156
1240
  200:
1157
- description: FIDO device pre-registered.
1241
+ description: FIDO device pre-registered data
1158
1242
  400:
1159
- description: Invalid password
1160
- Wrong or expired token
1161
- Inactive user
1243
+ description: Invalid request
1162
1244
  """
1163
1245
  return auth_service.pre_register_fido(
1164
1246
  persons_service.get_current_user()["id"]
@@ -1168,18 +1250,33 @@ class FIDOResource(Resource, ArgsMixin):
1168
1250
  @jwt_required()
1169
1251
  def post(self):
1170
1252
  """
1171
- Resource to allow a user to register a FIDO device.
1253
+ Register FIDO device
1172
1254
  ---
1173
- description: ""
1255
+ description: Register a FIDO device for WebAuthn authentication.
1256
+ It requires registration response from the device.
1174
1257
  tags:
1175
1258
  - Authentication
1259
+ requestBody:
1260
+ required: true
1261
+ content:
1262
+ application/json:
1263
+ schema:
1264
+ type: object
1265
+ properties:
1266
+ registration_response:
1267
+ type: object
1268
+ description: FIDO device registration response
1269
+ device_name:
1270
+ type: string
1271
+ description: Name for the FIDO device
1272
+ required:
1273
+ - registration_response
1274
+ - device_name
1176
1275
  responses:
1177
1276
  200:
1178
- description: FIDO device registered.
1277
+ description: FIDO device registered
1179
1278
  400:
1180
- description: Invalid password
1181
- Wrong or expired token
1182
- Inactive user
1279
+ description: Registration failed or no preregistration
1183
1280
  """
1184
1281
  try:
1185
1282
  args = self.get_args(
@@ -1213,19 +1310,41 @@ class FIDOResource(Resource, ArgsMixin):
1213
1310
  @permissions.require_person
1214
1311
  def delete(self):
1215
1312
  """
1216
- Resource to allow a user to unregister a FIDO device.
1313
+ Unregister FIDO device
1217
1314
  ---
1218
- description: ""
1315
+ description: Unregister a FIDO device from WebAuthn authentication.
1316
+ It requires two-factor authentication verification.
1219
1317
  tags:
1220
1318
  - Authentication
1319
+ requestBody:
1320
+ required: true
1321
+ content:
1322
+ application/json:
1323
+ schema:
1324
+ type: object
1325
+ properties:
1326
+ totp:
1327
+ type: string
1328
+ description: TOTP verification code
1329
+ email_otp:
1330
+ type: string
1331
+ description: Email OTP verification code
1332
+ fido_authentication_response:
1333
+ type: object
1334
+ description: FIDO authentication response
1335
+ recovery_code:
1336
+ type: string
1337
+ description: Recovery code for two-factor authentication
1338
+ device_name:
1339
+ type: string
1340
+ description: Name of the FIDO device to unregister
1341
+ required:
1342
+ - device_name
1221
1343
  responses:
1222
1344
  200:
1223
- description: FIDO device unregistered.
1345
+ description: FIDO device unregistered
1224
1346
  400:
1225
- description: Invalid password
1226
- Wrong or expired token
1227
- Inactive user
1228
- Wrong 2FA
1347
+ description: FIDO not enabled or verification failed
1229
1348
  """
1230
1349
  args = self.get_args(
1231
1350
  [
@@ -1270,26 +1389,41 @@ class FIDOResource(Resource, ArgsMixin):
1270
1389
 
1271
1390
 
1272
1391
  class RecoveryCodesResource(Resource, ArgsMixin):
1273
- """
1274
- Resource to allow a user to generate new recovery codes.
1275
- """
1276
1392
 
1277
1393
  @jwt_required()
1278
1394
  @permissions.require_person
1279
1395
  def put(self):
1280
1396
  """
1281
- Resource to allow a user to generate new recovery codes.
1397
+ Generate recovery codes
1282
1398
  ---
1283
- description: ""
1399
+ description: Generate new recovery codes for two-factor authentication.
1400
+ It requires two-factor authentication verification.
1284
1401
  tags:
1285
1402
  - Authentication
1403
+ requestBody:
1404
+ required: true
1405
+ content:
1406
+ application/json:
1407
+ schema:
1408
+ type: object
1409
+ properties:
1410
+ totp:
1411
+ type: string
1412
+ description: TOTP verification code
1413
+ email_otp:
1414
+ type: string
1415
+ description: Email OTP verification code
1416
+ fido_authentication_response:
1417
+ type: object
1418
+ description: FIDO authentication response
1419
+ recovery_code:
1420
+ type: string
1421
+ description: Recovery code for two-factor authentication
1286
1422
  responses:
1287
1423
  200:
1288
- description: new recovery codes.
1424
+ description: New recovery codes generated
1289
1425
  400:
1290
- description: Invalid password
1291
- Wrong or expired token
1292
- Inactive user
1426
+ description: No two-factor authentication enabled or verification failed
1293
1427
  """
1294
1428
  args = self.get_args(
1295
1429
  [
@@ -1338,22 +1472,20 @@ class RecoveryCodesResource(Resource, ArgsMixin):
1338
1472
 
1339
1473
 
1340
1474
  class SAMLSSOResource(Resource, ArgsMixin):
1341
- """
1342
- Resource to allow a user to login with SAML SSO.
1343
- """
1344
-
1345
1475
  def post(self):
1346
1476
  """
1347
- Resource to allow a user to login with SAML SSO.
1477
+ SAML SSO login
1348
1478
  ---
1349
- description: ""
1479
+ description: Handle SAML SSO login response. Processes authentication
1480
+ response from SAML identity provider and creates a new user if they
1481
+ don't exist.
1350
1482
  tags:
1351
1483
  - Authentication
1352
1484
  responses:
1353
1485
  302:
1354
- description: Login successful, redirect to the home page.
1486
+ description: Login successful, redirect to home page
1355
1487
  400:
1356
- description: Wrong parameter
1488
+ description: SAML not enabled or wrong parameter
1357
1489
  """
1358
1490
  if not config.SAML_ENABLED:
1359
1491
  return {"error": "SAML is not enabled."}, 400
@@ -1429,22 +1561,20 @@ class SAMLSSOResource(Resource, ArgsMixin):
1429
1561
 
1430
1562
 
1431
1563
  class SAMLLoginResource(Resource, ArgsMixin):
1432
- """
1433
- Resource to allow a user to login with SAML SSO.
1434
- """
1435
1564
 
1436
1565
  def get(self):
1437
1566
  """
1438
- Resource to allow a user to login with SAML SSO.
1567
+ SAML SSO login redirect
1439
1568
  ---
1440
- description: ""
1569
+ description: Initiate SAML SSO login by redirecting to SAML identity
1570
+ provider.
1441
1571
  tags:
1442
1572
  - Authentication
1443
1573
  responses:
1444
1574
  302:
1445
- description: Redirect to the SAML IDP.
1575
+ description: Redirect to SAML identity provider
1446
1576
  400:
1447
- description: Wrong parameter.
1577
+ description: SAML not enabled or wrong parameter
1448
1578
  """
1449
1579
  if not config.SAML_ENABLED:
1450
1580
  return {"error": "SAML is not enabled."}, 400