Enhance 2FA handling and subuser session management

- Add `two_factor_enabled` property for subuser responses in routes and OpenAPI specs.
- Improve subuser session resolution by checking token `id` for validity.
- Adjust authentication flow to prevent operations on nonexistent users in 2FA logic.
- Update OpenAPI request/response schema to better represent token/session objects.
This commit is contained in:
Jeppe Bundgaard
2026-02-23 21:44:11 +01:00
parent ce889053a6
commit eb0f4ca38b
4 changed files with 24 additions and 10 deletions
+19 -8
View File
@@ -513,6 +513,9 @@ paths:
type: string
format: date-time
nullable: true
two_factor_enabled:
type: boolean
description: Indicates if 2FA is enabled for this account
permissions:
type: array
description: Aggregated permission keys granted for the caller's customer
@@ -1277,14 +1280,19 @@ paths:
content:
application/json:
schema:
type: object
properties:
token:
type: string
description: Bearer authentication token (for users/employees)
session:
type: string
description: Session token (for subusers)
oneOf:
- type: object
required: [token]
properties:
token:
type: string
description: Bearer authentication token (for users/employees)
- type: object
required: [session]
properties:
session:
type: string
description: Session token (for subusers)
'400':
$ref: '#/components/responses/BadRequest'
'401':
@@ -7205,6 +7213,9 @@ components:
type: string
format: date-time
nullable: true
two_factor_enabled:
type: boolean
description: Indicates if 2FA is enabled for this account
PermissionNode:
type: object
+2 -1
View File
@@ -292,8 +292,9 @@ class subusers_o extends db
}
// Fallback: resolve via tokens table if cache is missing/expired
try {
// tokens_o::getToken() might throw Exception if not found
$tok = (new tokens_o())->getToken($token);
if ($tok && $tok->type->value() === 'AUTH_TOKEN_SUBUSER') {
if ($tok && $tok->id && $tok->type->value() === 'AUTH_TOKEN_SUBUSER') {
$resolvedId = (int)$tok->user_id->value();
// Re-cache mapping for future lookups (7 days to match session lifetime)
$this->cache($cache_key, $resolvedId, $cache_object_id);
+1 -1
View File
@@ -55,7 +55,7 @@ class authRoute
}
// If the credentials are valid, create a token
$user = (new users_o())->getUserByCustomerNumber($data['customer_number']);
if ($user->isTwoFactorEnabled()) {
if ($user->exists() && $user->isTwoFactorEnabled()) {
$token = (new authentication())->create_2fa_token($user->id, '2FA_VERIFICATION_USER');
$response->success(['2fa_required' => true, '2fa_token' => $token]);
}
@@ -553,6 +553,7 @@ class subusersRoute
'updated_at' => $o->updated_at ?? null,
'suspended_at' => $o->suspended_at ?? null,
'permissions' => $permissions,
'two_factor_enabled' => $o->isTwoFactorEnabled(),
];
}, null, [], $existsClause);
@@ -589,6 +590,7 @@ class subusersRoute
"created_at" => $subuser->created_at->value() ?? null,
"updated_at" => $subuser->updated_at->value() ?? null,
"suspended_at" => $subuser->suspended_at->value() ?? null,
"two_factor_enabled" => $subuser->isTwoFactorEnabled(),
];
$response->success($result);
}, []);