Merge pull request #49443 from nextcloud/feat/issue-994-two-factor-api

feat: Two Factor API
This commit is contained in:
Sebastian Krupinski 2025-01-18 19:03:16 +00:00 committed by GitHub
commit 307f983431
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 449 additions and 0 deletions

View file

@ -0,0 +1,99 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Core\Controller;
use OC\Authentication\TwoFactorAuth\ProviderManager;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\ApiRoute;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\Authentication\TwoFactorAuth\IRegistry;
use OCP\IRequest;
use OCP\IUserManager;
class TwoFactorApiController extends OCSController {
public function __construct(
string $appName,
IRequest $request,
private ProviderManager $tfManager,
private IRegistry $tfRegistry,
private IUserManager $userManager,
) {
parent::__construct($appName, $request);
}
/**
* Get two factor authentication provider states
*
* @param string $user system user id
*
* @return DataResponse<Http::STATUS_OK, array<string, bool>, array{}>|DataResponse<Http::STATUS_NOT_FOUND, null, array{}>
*
* 200: provider states
* 404: user not found
*/
#[ApiRoute(verb: 'GET', url: '/state', root: '/twofactor')]
public function state(string $user): DataResponse {
$userObject = $this->userManager->get($user);
if ($userObject !== null) {
$state = $this->tfRegistry->getProviderStates($userObject);
return new DataResponse($state);
}
return new DataResponse(null, Http::STATUS_NOT_FOUND);
}
/**
* Enable two factor authentication providers for specific user
*
* @param string $user system user identifier
* @param list<string> $providers collection of TFA provider ids
*
* @return DataResponse<Http::STATUS_OK, array<string, bool>, array{}>|DataResponse<Http::STATUS_NOT_FOUND, null, array{}>
*
* 200: provider states
* 404: user not found
*/
#[ApiRoute(verb: 'POST', url: '/enable', root: '/twofactor')]
public function enable(string $user, array $providers = []): DataResponse {
$userObject = $this->userManager->get($user);
if ($userObject !== null) {
foreach ($providers as $providerId) {
$this->tfManager->tryEnableProviderFor($providerId, $userObject);
}
$state = $this->tfRegistry->getProviderStates($userObject);
return new DataResponse($state);
}
return new DataResponse(null, Http::STATUS_NOT_FOUND);
}
/**
* Disable two factor authentication providers for specific user
*
* @param string $user system user identifier
* @param list<string> $providers collection of TFA provider ids
*
* @return DataResponse<Http::STATUS_OK, array<string, bool>, array{}>|DataResponse<Http::STATUS_NOT_FOUND, null, array{}>
*
* 200: provider states
* 404: user not found
*/
#[ApiRoute(verb: 'POST', url: '/disable', root: '/twofactor')]
public function disable(string $user, array $providers = []): DataResponse {
$userObject = $this->userManager->get($user);
if ($userObject !== null) {
foreach ($providers as $providerId) {
$this->tfManager->tryDisableProviderFor($providerId, $userObject);
}
$state = $this->tfRegistry->getProviderStates($userObject);
return new DataResponse($state);
}
return new DataResponse(null, Http::STATUS_NOT_FOUND);
}
}

View file

@ -9514,6 +9514,354 @@
}
}
}
},
"/ocs/v2.php/twofactor/state": {
"get": {
"operationId": "two_factor_api-state",
"summary": "Get two factor authentication provider states",
"description": "This endpoint requires admin access",
"tags": [
"two_factor_api"
],
"security": [
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"parameters": [
{
"name": "user",
"in": "query",
"description": "system user id",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "OCS-APIRequest",
"in": "header",
"description": "Required to be true for the API request to pass",
"required": true,
"schema": {
"type": "boolean",
"default": true
}
}
],
"responses": {
"200": {
"description": "provider states",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"additionalProperties": {
"type": "boolean"
}
}
}
}
}
}
}
}
},
"404": {
"description": "user not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"nullable": true
}
}
}
}
}
}
}
}
}
}
},
"/ocs/v2.php/twofactor/enable": {
"post": {
"operationId": "two_factor_api-enable",
"summary": "Enable two factor authentication providers for specific user",
"description": "This endpoint requires admin access",
"tags": [
"two_factor_api"
],
"security": [
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"user"
],
"properties": {
"user": {
"type": "string",
"description": "system user identifier"
},
"providers": {
"type": "array",
"default": [],
"description": "collection of TFA provider ids",
"items": {
"type": "string"
}
}
}
}
}
}
},
"parameters": [
{
"name": "OCS-APIRequest",
"in": "header",
"description": "Required to be true for the API request to pass",
"required": true,
"schema": {
"type": "boolean",
"default": true
}
}
],
"responses": {
"200": {
"description": "provider states",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"additionalProperties": {
"type": "boolean"
}
}
}
}
}
}
}
}
},
"404": {
"description": "user not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"nullable": true
}
}
}
}
}
}
}
}
}
}
},
"/ocs/v2.php/twofactor/disable": {
"post": {
"operationId": "two_factor_api-disable",
"summary": "Disable two factor authentication providers for specific user",
"description": "This endpoint requires admin access",
"tags": [
"two_factor_api"
],
"security": [
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"user"
],
"properties": {
"user": {
"type": "string",
"description": "system user identifier"
},
"providers": {
"type": "array",
"default": [],
"description": "collection of TFA provider ids",
"items": {
"type": "string"
}
}
}
}
}
}
},
"parameters": [
{
"name": "OCS-APIRequest",
"in": "header",
"description": "Required to be true for the API request to pass",
"required": true,
"schema": {
"type": "boolean",
"default": true
}
}
],
"responses": {
"200": {
"description": "provider states",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"additionalProperties": {
"type": "boolean"
}
}
}
}
}
}
}
}
},
"404": {
"description": "user not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"nullable": true
}
}
}
}
}
}
}
}
}
}
}
},
"tags": [

View file

@ -1336,6 +1336,7 @@ return array(
'OC\\Core\\Controller\\TextProcessingApiController' => $baseDir . '/core/Controller/TextProcessingApiController.php',
'OC\\Core\\Controller\\TextToImageApiController' => $baseDir . '/core/Controller/TextToImageApiController.php',
'OC\\Core\\Controller\\TranslationApiController' => $baseDir . '/core/Controller/TranslationApiController.php',
'OC\\Core\\Controller\\TwoFactorApiController' => $baseDir . '/core/Controller/TwoFactorApiController.php',
'OC\\Core\\Controller\\TwoFactorChallengeController' => $baseDir . '/core/Controller/TwoFactorChallengeController.php',
'OC\\Core\\Controller\\UnifiedSearchController' => $baseDir . '/core/Controller/UnifiedSearchController.php',
'OC\\Core\\Controller\\UnsupportedBrowserController' => $baseDir . '/core/Controller/UnsupportedBrowserController.php',

View file

@ -1385,6 +1385,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Core\\Controller\\TextProcessingApiController' => __DIR__ . '/../../..' . '/core/Controller/TextProcessingApiController.php',
'OC\\Core\\Controller\\TextToImageApiController' => __DIR__ . '/../../..' . '/core/Controller/TextToImageApiController.php',
'OC\\Core\\Controller\\TranslationApiController' => __DIR__ . '/../../..' . '/core/Controller/TranslationApiController.php',
'OC\\Core\\Controller\\TwoFactorApiController' => __DIR__ . '/../../..' . '/core/Controller/TwoFactorApiController.php',
'OC\\Core\\Controller\\TwoFactorChallengeController' => __DIR__ . '/../../..' . '/core/Controller/TwoFactorChallengeController.php',
'OC\\Core\\Controller\\UnifiedSearchController' => __DIR__ . '/../../..' . '/core/Controller/UnifiedSearchController.php',
'OC\\Core\\Controller\\UnsupportedBrowserController' => __DIR__ . '/../../..' . '/core/Controller/UnsupportedBrowserController.php',