1
0
Fork 0
mirror of synced 2024-06-01 18:39:57 +12:00

Add recovery codes to users API

This commit is contained in:
Matej Bačo 2024-03-03 15:17:38 +00:00
parent 9137dc82f8
commit 9bcad451f2
5 changed files with 135 additions and 1 deletions

View file

@ -3712,7 +3712,7 @@ App::post('/v1/account/mfa/recovery-codes')
->label('sdk.namespace', 'account')
->label('sdk.method', 'createMfaRecoveryCodes')
->label('sdk.description', '/docs/references/account/create-mfa-recovery-codes.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES)
->label('sdk.offline.model', '/account')
@ -3765,6 +3765,11 @@ App::put('/v1/account/mfa/recovery-codes')
->inject('queueForEvents')
->action(function (Database $dbForProject, Response $response, Document $user, Event $queueForEvents) {
$mfaRecoveryCodes = $user->getAttribute('mfaRecoveryCodes', []);
if (empty($mfaRecoveryCodes)) {
throw new Exception(Exception::USER_RECOVERY_CODES_NOT_FOUND);
}
$mfaRecoveryCodes = Type::generateBackupCodes();
$user->setAttribute('mfaRecoveryCodes', $mfaRecoveryCodes);
$dbForProject->updateDocument('users', $user->getId(), $user);

View file

@ -1591,6 +1591,132 @@ App::get('/v1/users/:userId/mfa/factors')
$response->dynamic($factors, Response::MODEL_MFA_FACTORS);
});
App::get('/v1/users/:userId/mfa/recovery-codes')
->desc('Get MFA Recovery Codes')
->groups(['api', 'users'])
->label('scope', 'users.read')
->label('usage.metric', 'users.{scope}.requests.read')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'getMfaRecoveryCodes')
->label('sdk.description', '/docs/references/users/get-mfa-recovery-codes.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES)
->param('userId', '', new UID(), 'User ID.')
->inject('response')
->inject('dbForProject')
->action(function (string $userId, Response $response, Database $dbForProject) {
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty()) {
throw new Exception(Exception::USER_NOT_FOUND);
}
$mfaRecoveryCodes = $user->getAttribute('mfaRecoveryCodes', []);
if (empty($mfaRecoveryCodes)) {
throw new Exception(Exception::USER_RECOVERY_CODES_NOT_FOUND);
}
$document = new Document([
'recoveryCodes' => $mfaRecoveryCodes
]);
$response->dynamic($document, Response::MODEL_MFA_RECOVERY_CODES);
});
App::post('/v1/users/:userId/mfa/recovery-codes')
->desc('Create MFA Recovery Codes')
->groups(['api', 'users'])
->label('event', 'users.[userId].create.mfa.recovery-codes')
->label('scope', 'users.write')
->label('audits.event', 'user.update')
->label('audits.resource', 'user/{response.$id}')
->label('audits.userId', '{response.$id}')
->label('usage.metric', 'users.{scope}.requests.update')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'createMfaRecoveryCodes')
->label('sdk.description', '/docs/references/users/create-mfa-recovery-codes.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES)
->param('userId', '', new UID(), 'User ID.')
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $userId, string $type, Response $response, Database $dbForProject, Event $queueForEvents) {
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty()) {
throw new Exception(Exception::USER_NOT_FOUND);
}
$mfaRecoveryCodes = $user->getAttribute('mfaRecoveryCodes', []);
if (!empty($mfaRecoveryCodes)) {
throw new Exception(Exception::USER_RECOVERY_CODES_ALREADY_EXISTS);
}
$mfaRecoveryCodes = Type::generateBackupCodes();
$user->setAttribute('mfaRecoveryCodes', $mfaRecoveryCodes);
$dbForProject->updateDocument('users', $user->getId(), $user);
$queueForEvents->setParam('userId', $user->getId());
$document = new Document([
'recoveryCodes' => $mfaRecoveryCodes
]);
$response->dynamic($document, Response::MODEL_MFA_RECOVERY_CODES);
});
App::put('/v1/users/:userId/mfa/recovery-codes')
->desc('Regenerate MFA Recovery Codes')
->groups(['api', 'users'])
->label('event', 'users.[userId].update.mfa.recovery-codes')
->label('scope', 'users.write')
->label('audits.event', 'user.update')
->label('audits.resource', 'user/{response.$id}')
->label('audits.userId', '{response.$id}')
->label('usage.metric', 'users.{scope}.requests.update')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'updateMfaRecoveryCodes')
->label('sdk.description', '/docs/references/users/update-mfa-recovery-codes.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES)
->param('userId', '', new UID(), 'User ID.')
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $userId, string $type, Response $response, Database $dbForProject, Event $queueForEvents) {
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty()) {
throw new Exception(Exception::USER_NOT_FOUND);
}
$mfaRecoveryCodes = $user->getAttribute('mfaRecoveryCodes', []);
if (empty($mfaRecoveryCodes)) {
throw new Exception(Exception::USER_RECOVERY_CODES_NOT_FOUND);
}
$mfaRecoveryCodes = Type::generateBackupCodes();
$user->setAttribute('mfaRecoveryCodes', $mfaRecoveryCodes);
$dbForProject->updateDocument('users', $user->getId(), $user);
$queueForEvents->setParam('userId', $user->getId());
$document = new Document([
'recoveryCodes' => $mfaRecoveryCodes
]);
$response->dynamic($document, Response::MODEL_MFA_RECOVERY_CODES);
});
App::delete('/v1/users/:userId/mfa/authenticators/:type')
->desc('Delete Authenticator')
->groups(['api', 'users'])

View file

@ -0,0 +1 @@
Generate recovery codes used as backup for MFA flow for User ID. Recovery codes can be used as a MFA verification type in [createMfaChallenge](/docs/references/cloud/client-web/account#createMfaChallenge) method by client SDK.

View file

@ -0,0 +1 @@
Get recovery codes that can be used as backup for MFA flow by User ID. Before getting codes, they must be generated using [createMfaRecoveryCodes](/docs/references/cloud/client-web/account#createMfaRecoveryCodes) method.

View file

@ -0,0 +1 @@
Regenerate recovery codes that can be used as backup for MFA flow by User ID. Before regenerating codes, they must be first generated using [createMfaRecoveryCodes](/docs/references/cloud/client-web/account#createMfaRecoveryCodes) method.