Passed
Push — master ( f9d30b...528eb1 )
by Roeland
22:26 queued 10:54
created
core/routes.php 1 patch
Indentation   +78 added lines, -78 removed lines patch added patch discarded remove patch
@@ -36,86 +36,86 @@  discard block
 block discarded – undo
36 36
 
37 37
 $application = new Application();
38 38
 $application->registerRoutes($this, [
39
-	'routes' => [
40
-		['name' => 'lost#email', 'url' => '/lostpassword/email', 'verb' => 'POST'],
41
-		['name' => 'lost#resetform', 'url' => '/lostpassword/reset/form/{token}/{userId}', 'verb' => 'GET'],
42
-		['name' => 'lost#setPassword', 'url' => '/lostpassword/set/{token}/{userId}', 'verb' => 'POST'],
43
-		['name' => 'user#getDisplayNames', 'url' => '/displaynames', 'verb' => 'POST'],
44
-		['name' => 'avatar#getAvatar', 'url' => '/avatar/{userId}/{size}', 'verb' => 'GET'],
45
-		['name' => 'avatar#deleteAvatar', 'url' => '/avatar/', 'verb' => 'DELETE'],
46
-		['name' => 'avatar#postCroppedAvatar', 'url' => '/avatar/cropped', 'verb' => 'POST'],
47
-		['name' => 'avatar#getTmpAvatar', 'url' => '/avatar/tmp', 'verb' => 'GET'],
48
-		['name' => 'avatar#postAvatar', 'url' => '/avatar/', 'verb' => 'POST'],
49
-		['name' => 'GuestAvatar#getAvatar', 'url' => '/avatar/guest/{guestName}/{size}', 'verb' => 'GET'],
50
-		['name' => 'CSRFToken#index', 'url' => '/csrftoken', 'verb' => 'GET'],
51
-		['name' => 'login#tryLogin', 'url' => '/login', 'verb' => 'POST'],
52
-		['name' => 'login#confirmPassword', 'url' => '/login/confirm', 'verb' => 'POST'],
53
-		['name' => 'login#showLoginForm', 'url' => '/login', 'verb' => 'GET'],
54
-		['name' => 'login#logout', 'url' => '/logout', 'verb' => 'GET'],
55
-		// Original login flow used by all clients
56
-		['name' => 'ClientFlowLogin#showAuthPickerPage', 'url' => '/login/flow', 'verb' => 'GET'],
57
-		['name' => 'ClientFlowLogin#generateAppPassword', 'url' => '/login/flow', 'verb' => 'POST'],
58
-		['name' => 'ClientFlowLogin#grantPage', 'url' => '/login/flow/grant', 'verb' => 'GET'],
59
-		['name' => 'ClientFlowLogin#apptokenRedirect', 'url' => '/login/flow/apptoken', 'verb' => 'POST'],
60
-		// NG login flow used by desktop client in case of Kerberos/fancy 2fa (smart cards for example)
61
-		['name' => 'ClientFlowLoginV2#poll', 'url' => '/login/v2/poll', 'verb' => 'POST'],
62
-		['name' => 'ClientFlowLoginV2#showAuthPickerPage', 'url' => '/login/v2/flow', 'verb' => 'GET'],
63
-		['name' => 'ClientFlowLoginV2#landing', 'url' => '/login/v2/flow/{token}', 'verb' => 'GET'],
64
-		['name' => 'ClientFlowLoginV2#grantPage', 'url' => '/login/v2/grant', 'verb' => 'GET'],
65
-		['name' => 'ClientFlowLoginV2#generateAppPassword', 'url' => '/login/v2/grant', 'verb' => 'POST'],
66
-		['name' => 'ClientFlowLoginV2#init', 'url' => '/login/v2', 'verb' => 'POST'],
67
-		['name' => 'TwoFactorChallenge#selectChallenge', 'url' => '/login/selectchallenge', 'verb' => 'GET'],
68
-		['name' => 'TwoFactorChallenge#showChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'GET'],
69
-		['name' => 'TwoFactorChallenge#solveChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'POST'],
70
-		['name' => 'TwoFactorChallenge#setupProviders', 'url' => 'login/setupchallenge', 'verb' => 'GET'],
71
-		['name' => 'TwoFactorChallenge#setupProvider', 'url' => 'login/setupchallenge/{providerId}', 'verb' => 'GET'],
72
-		['name' => 'TwoFactorChallenge#confirmProviderSetup', 'url' => 'login/setupchallenge/{providerId}', 'verb' => 'POST'],
73
-		['name' => 'OCJS#getConfig', 'url' => '/core/js/oc.js', 'verb' => 'GET'],
74
-		['name' => 'Preview#getPreviewByFileId', 'url' => '/core/preview', 'verb' => 'GET'],
75
-		['name' => 'Preview#getPreview', 'url' => '/core/preview.png', 'verb' => 'GET'],
76
-		['name' => 'Svg#getSvgFromCore', 'url' => '/svg/core/{folder}/{fileName}', 'verb' => 'GET'],
77
-		['name' => 'Svg#getSvgFromApp', 'url' => '/svg/{app}/{fileName}', 'verb' => 'GET'],
78
-		['name' => 'Css#getCss', 'url' => '/css/{appName}/{fileName}', 'verb' => 'GET'],
79
-		['name' => 'Js#getJs', 'url' => '/js/{appName}/{fileName}', 'verb' => 'GET'],
80
-		['name' => 'contactsMenu#index', 'url' => '/contactsmenu/contacts', 'verb' => 'POST'],
81
-		['name' => 'contactsMenu#findOne', 'url' => '/contactsmenu/findOne', 'verb' => 'POST'],
82
-		['name' => 'WalledGarden#get', 'url' => '/204', 'verb' => 'GET'],
83
-		['name' => 'Search#search', 'url' => '/core/search', 'verb' => 'GET'],
39
+    'routes' => [
40
+        ['name' => 'lost#email', 'url' => '/lostpassword/email', 'verb' => 'POST'],
41
+        ['name' => 'lost#resetform', 'url' => '/lostpassword/reset/form/{token}/{userId}', 'verb' => 'GET'],
42
+        ['name' => 'lost#setPassword', 'url' => '/lostpassword/set/{token}/{userId}', 'verb' => 'POST'],
43
+        ['name' => 'user#getDisplayNames', 'url' => '/displaynames', 'verb' => 'POST'],
44
+        ['name' => 'avatar#getAvatar', 'url' => '/avatar/{userId}/{size}', 'verb' => 'GET'],
45
+        ['name' => 'avatar#deleteAvatar', 'url' => '/avatar/', 'verb' => 'DELETE'],
46
+        ['name' => 'avatar#postCroppedAvatar', 'url' => '/avatar/cropped', 'verb' => 'POST'],
47
+        ['name' => 'avatar#getTmpAvatar', 'url' => '/avatar/tmp', 'verb' => 'GET'],
48
+        ['name' => 'avatar#postAvatar', 'url' => '/avatar/', 'verb' => 'POST'],
49
+        ['name' => 'GuestAvatar#getAvatar', 'url' => '/avatar/guest/{guestName}/{size}', 'verb' => 'GET'],
50
+        ['name' => 'CSRFToken#index', 'url' => '/csrftoken', 'verb' => 'GET'],
51
+        ['name' => 'login#tryLogin', 'url' => '/login', 'verb' => 'POST'],
52
+        ['name' => 'login#confirmPassword', 'url' => '/login/confirm', 'verb' => 'POST'],
53
+        ['name' => 'login#showLoginForm', 'url' => '/login', 'verb' => 'GET'],
54
+        ['name' => 'login#logout', 'url' => '/logout', 'verb' => 'GET'],
55
+        // Original login flow used by all clients
56
+        ['name' => 'ClientFlowLogin#showAuthPickerPage', 'url' => '/login/flow', 'verb' => 'GET'],
57
+        ['name' => 'ClientFlowLogin#generateAppPassword', 'url' => '/login/flow', 'verb' => 'POST'],
58
+        ['name' => 'ClientFlowLogin#grantPage', 'url' => '/login/flow/grant', 'verb' => 'GET'],
59
+        ['name' => 'ClientFlowLogin#apptokenRedirect', 'url' => '/login/flow/apptoken', 'verb' => 'POST'],
60
+        // NG login flow used by desktop client in case of Kerberos/fancy 2fa (smart cards for example)
61
+        ['name' => 'ClientFlowLoginV2#poll', 'url' => '/login/v2/poll', 'verb' => 'POST'],
62
+        ['name' => 'ClientFlowLoginV2#showAuthPickerPage', 'url' => '/login/v2/flow', 'verb' => 'GET'],
63
+        ['name' => 'ClientFlowLoginV2#landing', 'url' => '/login/v2/flow/{token}', 'verb' => 'GET'],
64
+        ['name' => 'ClientFlowLoginV2#grantPage', 'url' => '/login/v2/grant', 'verb' => 'GET'],
65
+        ['name' => 'ClientFlowLoginV2#generateAppPassword', 'url' => '/login/v2/grant', 'verb' => 'POST'],
66
+        ['name' => 'ClientFlowLoginV2#init', 'url' => '/login/v2', 'verb' => 'POST'],
67
+        ['name' => 'TwoFactorChallenge#selectChallenge', 'url' => '/login/selectchallenge', 'verb' => 'GET'],
68
+        ['name' => 'TwoFactorChallenge#showChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'GET'],
69
+        ['name' => 'TwoFactorChallenge#solveChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'POST'],
70
+        ['name' => 'TwoFactorChallenge#setupProviders', 'url' => 'login/setupchallenge', 'verb' => 'GET'],
71
+        ['name' => 'TwoFactorChallenge#setupProvider', 'url' => 'login/setupchallenge/{providerId}', 'verb' => 'GET'],
72
+        ['name' => 'TwoFactorChallenge#confirmProviderSetup', 'url' => 'login/setupchallenge/{providerId}', 'verb' => 'POST'],
73
+        ['name' => 'OCJS#getConfig', 'url' => '/core/js/oc.js', 'verb' => 'GET'],
74
+        ['name' => 'Preview#getPreviewByFileId', 'url' => '/core/preview', 'verb' => 'GET'],
75
+        ['name' => 'Preview#getPreview', 'url' => '/core/preview.png', 'verb' => 'GET'],
76
+        ['name' => 'Svg#getSvgFromCore', 'url' => '/svg/core/{folder}/{fileName}', 'verb' => 'GET'],
77
+        ['name' => 'Svg#getSvgFromApp', 'url' => '/svg/{app}/{fileName}', 'verb' => 'GET'],
78
+        ['name' => 'Css#getCss', 'url' => '/css/{appName}/{fileName}', 'verb' => 'GET'],
79
+        ['name' => 'Js#getJs', 'url' => '/js/{appName}/{fileName}', 'verb' => 'GET'],
80
+        ['name' => 'contactsMenu#index', 'url' => '/contactsmenu/contacts', 'verb' => 'POST'],
81
+        ['name' => 'contactsMenu#findOne', 'url' => '/contactsmenu/findOne', 'verb' => 'POST'],
82
+        ['name' => 'WalledGarden#get', 'url' => '/204', 'verb' => 'GET'],
83
+        ['name' => 'Search#search', 'url' => '/core/search', 'verb' => 'GET'],
84 84
 
85
-		// Legacy routes that need to be globally available while they are handled by an app
86
-		['name' => 'viewcontroller#showFile', 'url' => '/f/{fileid}', 'verb' => 'GET', 'app' => 'files'],
87
-		['name' => 'sharecontroller#showShare', 'url' => '/s/{token}', 'verb' => 'GET', 'app' => 'files_sharing'],
88
-		['name' => 'sharecontroller#showAuthenticate', 'url' => '/s/{token}/authenticate/{redirect}', 'verb' => 'GET', 'app' => 'files_sharing'],
89
-		['name' => 'sharecontroller#authenticate', 'url' => '/s/{token}/authenticate/{redirect}', 'verb' => 'POST', 'app' => 'files_sharing'],
90
-		['name' => 'sharecontroller#downloadShare', 'url' => '/s/{token}/download', 'verb' => 'GET', 'app' => 'files_sharing'],
91
-		['name' => 'publicpreview#directLink', 'url' => '/s/{token}/preview', 'verb' => 'GET', 'app' => 'files_sharing'],
92
-		['name' => 'requesthandlercontroller#addShare', 'url' => '/ocm/shares', 'verb' => 'POST', 'app' => 'cloud_federation_api'],
93
-		['name' => 'requesthandlercontroller#receiveNotification', 'url' => '/ocm/notifications', 'verb' => 'POST', 'app' => 'cloud_federation_api'],
94
-		['name' => 'pagecontroller#showCall', 'url' => '/call/{token}', 'verb' => 'GET', 'app' => 'spreed'],
95
-		['name' => 'pagecontroller#authenticatePassword', 'url' => '/call/{token}', 'verb' => 'POST', 'app' => 'spreed'],
96
-	],
97
-	'ocs' => [
98
-		['root' => '/cloud', 'name' => 'OCS#getCapabilities', 'url' => '/capabilities', 'verb' => 'GET'],
99
-		['root' => '', 'name' => 'OCS#getConfig', 'url' => '/config', 'verb' => 'GET'],
100
-		['root' => '/person', 'name' => 'OCS#personCheck', 'url' => '/check', 'verb' => 'POST'],
101
-		['root' => '/identityproof', 'name' => 'OCS#getIdentityProof', 'url' => '/key/{cloudId}', 'verb' => 'GET'],
102
-		['root' => '/core', 'name' => 'Navigation#getAppsNavigation', 'url' => '/navigation/apps', 'verb' => 'GET'],
103
-		['root' => '/core', 'name' => 'Navigation#getSettingsNavigation', 'url' => '/navigation/settings', 'verb' => 'GET'],
104
-		['root' => '/core', 'name' => 'AutoComplete#get', 'url' => '/autocomplete/get', 'verb' => 'GET'],
105
-		['root' => '/core', 'name' => 'WhatsNew#get', 'url' => '/whatsnew', 'verb' => 'GET'],
106
-		['root' => '/core', 'name' => 'WhatsNew#dismiss', 'url' => '/whatsnew', 'verb' => 'POST'],
107
-		['root' => '/core', 'name' => 'AppPassword#getAppPassword', 'url' => '/getapppassword', 'verb' => 'GET'],
108
-		['root' => '/core', 'name' => 'AppPassword#deleteAppPassword', 'url' => '/apppassword', 'verb' => 'DELETE'],
85
+        // Legacy routes that need to be globally available while they are handled by an app
86
+        ['name' => 'viewcontroller#showFile', 'url' => '/f/{fileid}', 'verb' => 'GET', 'app' => 'files'],
87
+        ['name' => 'sharecontroller#showShare', 'url' => '/s/{token}', 'verb' => 'GET', 'app' => 'files_sharing'],
88
+        ['name' => 'sharecontroller#showAuthenticate', 'url' => '/s/{token}/authenticate/{redirect}', 'verb' => 'GET', 'app' => 'files_sharing'],
89
+        ['name' => 'sharecontroller#authenticate', 'url' => '/s/{token}/authenticate/{redirect}', 'verb' => 'POST', 'app' => 'files_sharing'],
90
+        ['name' => 'sharecontroller#downloadShare', 'url' => '/s/{token}/download', 'verb' => 'GET', 'app' => 'files_sharing'],
91
+        ['name' => 'publicpreview#directLink', 'url' => '/s/{token}/preview', 'verb' => 'GET', 'app' => 'files_sharing'],
92
+        ['name' => 'requesthandlercontroller#addShare', 'url' => '/ocm/shares', 'verb' => 'POST', 'app' => 'cloud_federation_api'],
93
+        ['name' => 'requesthandlercontroller#receiveNotification', 'url' => '/ocm/notifications', 'verb' => 'POST', 'app' => 'cloud_federation_api'],
94
+        ['name' => 'pagecontroller#showCall', 'url' => '/call/{token}', 'verb' => 'GET', 'app' => 'spreed'],
95
+        ['name' => 'pagecontroller#authenticatePassword', 'url' => '/call/{token}', 'verb' => 'POST', 'app' => 'spreed'],
96
+    ],
97
+    'ocs' => [
98
+        ['root' => '/cloud', 'name' => 'OCS#getCapabilities', 'url' => '/capabilities', 'verb' => 'GET'],
99
+        ['root' => '', 'name' => 'OCS#getConfig', 'url' => '/config', 'verb' => 'GET'],
100
+        ['root' => '/person', 'name' => 'OCS#personCheck', 'url' => '/check', 'verb' => 'POST'],
101
+        ['root' => '/identityproof', 'name' => 'OCS#getIdentityProof', 'url' => '/key/{cloudId}', 'verb' => 'GET'],
102
+        ['root' => '/core', 'name' => 'Navigation#getAppsNavigation', 'url' => '/navigation/apps', 'verb' => 'GET'],
103
+        ['root' => '/core', 'name' => 'Navigation#getSettingsNavigation', 'url' => '/navigation/settings', 'verb' => 'GET'],
104
+        ['root' => '/core', 'name' => 'AutoComplete#get', 'url' => '/autocomplete/get', 'verb' => 'GET'],
105
+        ['root' => '/core', 'name' => 'WhatsNew#get', 'url' => '/whatsnew', 'verb' => 'GET'],
106
+        ['root' => '/core', 'name' => 'WhatsNew#dismiss', 'url' => '/whatsnew', 'verb' => 'POST'],
107
+        ['root' => '/core', 'name' => 'AppPassword#getAppPassword', 'url' => '/getapppassword', 'verb' => 'GET'],
108
+        ['root' => '/core', 'name' => 'AppPassword#deleteAppPassword', 'url' => '/apppassword', 'verb' => 'DELETE'],
109 109
 
110
-		['root' => '/collaboration', 'name' => 'CollaborationResources#searchCollections', 'url' => '/resources/collections/search/{filter}', 'verb' => 'GET'],
111
-		['root' => '/collaboration', 'name' => 'CollaborationResources#listCollection', 'url' => '/resources/collections/{collectionId}', 'verb' => 'GET'],
112
-		['root' => '/collaboration', 'name' => 'CollaborationResources#renameCollection', 'url' => '/resources/collections/{collectionId}', 'verb' => 'PUT'],
113
-		['root' => '/collaboration', 'name' => 'CollaborationResources#addResource', 'url' => '/resources/collections/{collectionId}', 'verb' => 'POST'],
110
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#searchCollections', 'url' => '/resources/collections/search/{filter}', 'verb' => 'GET'],
111
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#listCollection', 'url' => '/resources/collections/{collectionId}', 'verb' => 'GET'],
112
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#renameCollection', 'url' => '/resources/collections/{collectionId}', 'verb' => 'PUT'],
113
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#addResource', 'url' => '/resources/collections/{collectionId}', 'verb' => 'POST'],
114 114
 
115
-		['root' => '/collaboration', 'name' => 'CollaborationResources#removeResource', 'url' => '/resources/collections/{collectionId}', 'verb' => 'DELETE'],
116
-		['root' => '/collaboration', 'name' => 'CollaborationResources#getCollectionsByResource', 'url' => '/resources/{resourceType}/{resourceId}', 'verb' => 'GET'],
117
-		['root' => '/collaboration', 'name' => 'CollaborationResources#createCollectionOnResource', 'url' => '/resources/{baseResourceType}/{baseResourceId}', 'verb' => 'POST'],
118
-	],
115
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#removeResource', 'url' => '/resources/collections/{collectionId}', 'verb' => 'DELETE'],
116
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#getCollectionsByResource', 'url' => '/resources/{resourceType}/{resourceId}', 'verb' => 'GET'],
117
+        ['root' => '/collaboration', 'name' => 'CollaborationResources#createCollectionOnResource', 'url' => '/resources/{baseResourceType}/{baseResourceId}', 'verb' => 'POST'],
118
+    ],
119 119
 ]);
120 120
 
121 121
 // Post installation check
@@ -124,4 +124,4 @@  discard block
 block discarded – undo
124 124
 // Core ajax actions
125 125
 // Routing
126 126
 $this->create('core_ajax_update', '/core/ajax/update.php')
127
-	->actionInclude('core/ajax/update.php');
127
+    ->actionInclude('core/ajax/update.php');
Please login to merge, or discard this patch.
core/templates/twofactorselectchallenge.php 2 patches
Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -20,10 +20,10 @@  discard block
 block discarded – undo
20 20
 			<?php } else { ?>
21 21
 				<strong><?php p($l->t('Two-factor authentication is enforced but has not been configured on your account. Please continue to setup two-factor authentication.')) ?></strong>
22 22
 				<a class="button primary two-factor-primary" href="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.setupProviders',
23
-					[
24
-						'redirect_url' => $_['redirect_url'],
25
-					]
26
-				)) ?>">
23
+                    [
24
+                        'redirect_url' => $_['redirect_url'],
25
+                    ]
26
+                )) ?>">
27 27
 					<?php p($l->t('Set up two-factor authentication')) ?>
28 28
 				</a>
29 29
 			<?php } ?>
@@ -37,18 +37,18 @@  discard block
 block discarded – undo
37 37
 		<li>
38 38
 			<a class="two-factor-provider"
39 39
 			   href="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.showChallenge',
40
-								[
41
-									'challengeProviderId' => $provider->getId(),
42
-									'redirect_url' => $_['redirect_url'],
43
-								]
44
-							)) ?>">
40
+                                [
41
+                                    'challengeProviderId' => $provider->getId(),
42
+                                    'redirect_url' => $_['redirect_url'],
43
+                                ]
44
+                            )) ?>">
45 45
 				<?php
46
-				if ($provider instanceof \OCP\Authentication\TwoFactorAuth\IProvidesIcons) {
47
-					$icon = $provider->getLightIcon();
48
-				} else {
49
-					$icon = image_path('core', 'actions/password-white.svg');
50
-				}
51
-				?>
46
+                if ($provider instanceof \OCP\Authentication\TwoFactorAuth\IProvidesIcons) {
47
+                    $icon = $provider->getLightIcon();
48
+                } else {
49
+                    $icon = image_path('core', 'actions/password-white.svg');
50
+                }
51
+                ?>
52 52
 				<img src="<?php p($icon) ?>" alt="" />
53 53
 				<div>
54 54
 					<h3><?php p($provider->getDisplayName()) ?></h3>
@@ -62,11 +62,11 @@  discard block
 block discarded – undo
62 62
 	<?php if (!is_null($_['backupProvider'])): ?>
63 63
 	<p>
64 64
 		<a class="<?php if($noProviders): ?>button primary two-factor-primary<?php else: ?>two-factor-secondary<?php endif ?>" href="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.showChallenge',
65
-			[
66
-				'challengeProviderId' => $_['backupProvider']->getId(),
67
-				'redirect_url' => $_['redirect_url'],
68
-			]
69
-		)) ?>">
65
+            [
66
+                'challengeProviderId' => $_['backupProvider']->getId(),
67
+                'redirect_url' => $_['redirect_url'],
68
+            ]
69
+        )) ?>">
70 70
 			<?php p($l->t('Use backup code')) ?>
71 71
 		</a>
72 72
 	</p>
Please login to merge, or discard this patch.
Braces   +13 added lines, -5 removed lines patch added patch discarded remove patch
@@ -27,11 +27,15 @@  discard block
 block discarded – undo
27 27
 					<?php p($l->t('Set up two-factor authentication')) ?>
28 28
 				</a>
29 29
 			<?php } ?>
30
-		<?php else: ?>
30
+		<?php else {
31
+    : ?>
31 32
 			<strong><?php p($l->t('Two-factor authentication is enforced but has not been configured on your account. Use one of your backup codes to log in or contact your admin for assistance.')) ?></strong>
32
-		<?php endif; ?>
33
+		<?php endif;
34
+}
35
+?>
33 36
 	</p>
34
-	<?php else: ?>
37
+	<?php else {
38
+    : ?>
35 39
 	<ul>
36 40
 	<?php foreach ($_['providers'] as $provider): ?>
37 41
 		<li>
@@ -45,6 +49,7 @@  discard block
 block discarded – undo
45 49
 				<?php
46 50
 				if ($provider instanceof \OCP\Authentication\TwoFactorAuth\IProvidesIcons) {
47 51
 					$icon = $provider->getLightIcon();
52
+}
48 53
 				} else {
49 54
 					$icon = image_path('core', 'actions/password-white.svg');
50 55
 				}
@@ -61,7 +66,8 @@  discard block
 block discarded – undo
61 66
 	<?php endif ?>
62 67
 	<?php if (!is_null($_['backupProvider'])): ?>
63 68
 	<p>
64
-		<a class="<?php if($noProviders): ?>button primary two-factor-primary<?php else: ?>two-factor-secondary<?php endif ?>" href="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.showChallenge',
69
+		<a class="<?php if($noProviders): ?>button primary two-factor-primary<?php else {
70
+    : ?>two-factor-secondary<?php endif ?>" href="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.showChallenge',
65 71
 			[
66 72
 				'challengeProviderId' => $_['backupProvider']->getId(),
67 73
 				'redirect_url' => $_['redirect_url'],
@@ -70,7 +76,9 @@  discard block
 block discarded – undo
70 76
 			<?php p($l->t('Use backup code')) ?>
71 77
 		</a>
72 78
 	</p>
73
-	<?php endif; ?>
79
+	<?php endif;
80
+}
81
+?>
74 82
 	<p><a class="two-factor-secondary" href="<?php print_unescaped($_['logout_url']); ?>">
75 83
 		<?php p($l->t('Cancel log in')) ?>
76 84
 	</a></p>
Please login to merge, or discard this patch.
core/templates/twofactorsetupselection.php 1 patch
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -31,18 +31,18 @@
 block discarded – undo
31 31
 		<li>
32 32
 			<a class="two-factor-provider"
33 33
 			   href="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.setupProvider',
34
-								[
35
-									'providerId' => $provider->getId(),
36
-									'redirect_url' => $_['redirect_url'],
37
-								]
38
-							)) ?>">
34
+                                [
35
+                                    'providerId' => $provider->getId(),
36
+                                    'redirect_url' => $_['redirect_url'],
37
+                                ]
38
+                            )) ?>">
39 39
 				<?php
40
-				if ($provider instanceof \OCP\Authentication\TwoFactorAuth\IProvidesIcons) {
41
-					$icon = $provider->getLightIcon();
42
-				} else {
43
-					$icon = image_path('core', 'actions/password-white.svg');
44
-				}
45
-				?>
40
+                if ($provider instanceof \OCP\Authentication\TwoFactorAuth\IProvidesIcons) {
41
+                    $icon = $provider->getLightIcon();
42
+                } else {
43
+                    $icon = image_path('core', 'actions/password-white.svg');
44
+                }
45
+                ?>
46 46
 				<img src="<?php p($icon) ?>" alt="" />
47 47
 				<div>
48 48
 					<h3><?php p($provider->getDisplayName()) ?></h3>
Please login to merge, or discard this patch.
core/Middleware/TwoFactorMiddleware.php 1 patch
Indentation   +101 added lines, -101 removed lines patch added patch discarded remove patch
@@ -44,106 +44,106 @@
 block discarded – undo
44 44
 
45 45
 class TwoFactorMiddleware extends Middleware {
46 46
 
47
-	/** @var Manager */
48
-	private $twoFactorManager;
49
-
50
-	/** @var Session */
51
-	private $userSession;
52
-
53
-	/** @var ISession */
54
-	private $session;
55
-
56
-	/** @var IURLGenerator */
57
-	private $urlGenerator;
58
-
59
-	/** @var IControllerMethodReflector */
60
-	private $reflector;
61
-
62
-	/** @var IRequest */
63
-	private $request;
64
-
65
-	/**
66
-	 * @param Manager $twoFactorManager
67
-	 * @param Session $userSession
68
-	 * @param ISession $session
69
-	 * @param IURLGenerator $urlGenerator
70
-	 */
71
-	public function __construct(Manager $twoFactorManager, Session $userSession, ISession $session,
72
-		IURLGenerator $urlGenerator, IControllerMethodReflector $reflector, IRequest $request) {
73
-		$this->twoFactorManager = $twoFactorManager;
74
-		$this->userSession = $userSession;
75
-		$this->session = $session;
76
-		$this->urlGenerator = $urlGenerator;
77
-		$this->reflector = $reflector;
78
-		$this->request = $request;
79
-	}
80
-
81
-	/**
82
-	 * @param Controller $controller
83
-	 * @param string $methodName
84
-	 */
85
-	public function beforeController($controller, $methodName) {
86
-		if ($this->reflector->hasAnnotation('PublicPage')) {
87
-			// Don't block public pages
88
-			return;
89
-		}
90
-
91
-		if ($controller instanceof ALoginSetupController
92
-			&& $this->userSession->getUser() !== null
93
-			&& $this->twoFactorManager->needsSecondFactor($this->userSession->getUser())) {
94
-			return;
95
-		}
96
-
97
-		if ($controller instanceof LoginController && $methodName === 'logout') {
98
-			// Don't block the logout page, to allow canceling the 2FA
99
-			return;
100
-		}
101
-
102
-		if ($this->userSession->isLoggedIn()) {
103
-			$user = $this->userSession->getUser();
104
-
105
-			if ($this->session->exists('app_password') || $this->twoFactorManager->isTwoFactorAuthenticated($user)) {
106
-				$this->checkTwoFactor($controller, $methodName, $user);
107
-			} else if ($controller instanceof TwoFactorChallengeController) {
108
-				// Allow access to the two-factor controllers only if two-factor authentication
109
-				// is in progress.
110
-				throw new UserAlreadyLoggedInException();
111
-			}
112
-		}
113
-		// TODO: dont check/enforce 2FA if a auth token is used
114
-	}
115
-
116
-	private function checkTwoFactor(Controller $controller, $methodName, IUser $user) {
117
-		// If two-factor auth is in progress disallow access to any controllers
118
-		// defined within "LoginController".
119
-		$needsSecondFactor = $this->twoFactorManager->needsSecondFactor($user);
120
-		$twoFactor = $controller instanceof TwoFactorChallengeController;
121
-
122
-		// Disallow access to any controller if 2FA needs to be checked
123
-		if ($needsSecondFactor && !$twoFactor) {
124
-			throw new TwoFactorAuthRequiredException();
125
-		}
126
-
127
-		// Allow access to the two-factor controllers only if two-factor authentication
128
-		// is in progress.
129
-		if (!$needsSecondFactor && $twoFactor) {
130
-			throw new UserAlreadyLoggedInException();
131
-		}
132
-	}
133
-
134
-	public function afterException($controller, $methodName, Exception $exception) {
135
-		if ($exception instanceof TwoFactorAuthRequiredException) {
136
-			$params = [];
137
-			if (isset($this->request->server['REQUEST_URI'])) {
138
-				$params['redirect_url'] = $this->request->server['REQUEST_URI'];
139
-			}
140
-			return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.selectChallenge', $params));
141
-		}
142
-		if ($exception instanceof UserAlreadyLoggedInException) {
143
-			return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index'));
144
-		}
145
-
146
-		throw $exception;
147
-	}
47
+    /** @var Manager */
48
+    private $twoFactorManager;
49
+
50
+    /** @var Session */
51
+    private $userSession;
52
+
53
+    /** @var ISession */
54
+    private $session;
55
+
56
+    /** @var IURLGenerator */
57
+    private $urlGenerator;
58
+
59
+    /** @var IControllerMethodReflector */
60
+    private $reflector;
61
+
62
+    /** @var IRequest */
63
+    private $request;
64
+
65
+    /**
66
+     * @param Manager $twoFactorManager
67
+     * @param Session $userSession
68
+     * @param ISession $session
69
+     * @param IURLGenerator $urlGenerator
70
+     */
71
+    public function __construct(Manager $twoFactorManager, Session $userSession, ISession $session,
72
+        IURLGenerator $urlGenerator, IControllerMethodReflector $reflector, IRequest $request) {
73
+        $this->twoFactorManager = $twoFactorManager;
74
+        $this->userSession = $userSession;
75
+        $this->session = $session;
76
+        $this->urlGenerator = $urlGenerator;
77
+        $this->reflector = $reflector;
78
+        $this->request = $request;
79
+    }
80
+
81
+    /**
82
+     * @param Controller $controller
83
+     * @param string $methodName
84
+     */
85
+    public function beforeController($controller, $methodName) {
86
+        if ($this->reflector->hasAnnotation('PublicPage')) {
87
+            // Don't block public pages
88
+            return;
89
+        }
90
+
91
+        if ($controller instanceof ALoginSetupController
92
+            && $this->userSession->getUser() !== null
93
+            && $this->twoFactorManager->needsSecondFactor($this->userSession->getUser())) {
94
+            return;
95
+        }
96
+
97
+        if ($controller instanceof LoginController && $methodName === 'logout') {
98
+            // Don't block the logout page, to allow canceling the 2FA
99
+            return;
100
+        }
101
+
102
+        if ($this->userSession->isLoggedIn()) {
103
+            $user = $this->userSession->getUser();
104
+
105
+            if ($this->session->exists('app_password') || $this->twoFactorManager->isTwoFactorAuthenticated($user)) {
106
+                $this->checkTwoFactor($controller, $methodName, $user);
107
+            } else if ($controller instanceof TwoFactorChallengeController) {
108
+                // Allow access to the two-factor controllers only if two-factor authentication
109
+                // is in progress.
110
+                throw new UserAlreadyLoggedInException();
111
+            }
112
+        }
113
+        // TODO: dont check/enforce 2FA if a auth token is used
114
+    }
115
+
116
+    private function checkTwoFactor(Controller $controller, $methodName, IUser $user) {
117
+        // If two-factor auth is in progress disallow access to any controllers
118
+        // defined within "LoginController".
119
+        $needsSecondFactor = $this->twoFactorManager->needsSecondFactor($user);
120
+        $twoFactor = $controller instanceof TwoFactorChallengeController;
121
+
122
+        // Disallow access to any controller if 2FA needs to be checked
123
+        if ($needsSecondFactor && !$twoFactor) {
124
+            throw new TwoFactorAuthRequiredException();
125
+        }
126
+
127
+        // Allow access to the two-factor controllers only if two-factor authentication
128
+        // is in progress.
129
+        if (!$needsSecondFactor && $twoFactor) {
130
+            throw new UserAlreadyLoggedInException();
131
+        }
132
+    }
133
+
134
+    public function afterException($controller, $methodName, Exception $exception) {
135
+        if ($exception instanceof TwoFactorAuthRequiredException) {
136
+            $params = [];
137
+            if (isset($this->request->server['REQUEST_URI'])) {
138
+                $params['redirect_url'] = $this->request->server['REQUEST_URI'];
139
+            }
140
+            return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.selectChallenge', $params));
141
+        }
142
+        if ($exception instanceof UserAlreadyLoggedInException) {
143
+            return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index'));
144
+        }
145
+
146
+        throw $exception;
147
+    }
148 148
 
149 149
 }
Please login to merge, or discard this patch.
core/Controller/TwoFactorChallengeController.php 1 patch
Indentation   +204 added lines, -204 removed lines patch added patch discarded remove patch
@@ -43,237 +43,237 @@
 block discarded – undo
43 43
 
44 44
 class TwoFactorChallengeController extends Controller {
45 45
 
46
-	/** @var Manager */
47
-	private $twoFactorManager;
46
+    /** @var Manager */
47
+    private $twoFactorManager;
48 48
 
49
-	/** @var IUserSession */
50
-	private $userSession;
49
+    /** @var IUserSession */
50
+    private $userSession;
51 51
 
52
-	/** @var ISession */
53
-	private $session;
52
+    /** @var ISession */
53
+    private $session;
54 54
 
55
-	/** @var IURLGenerator */
56
-	private $urlGenerator;
55
+    /** @var IURLGenerator */
56
+    private $urlGenerator;
57 57
 
58
-	/**
59
-	 * @param string $appName
60
-	 * @param IRequest $request
61
-	 * @param Manager $twoFactorManager
62
-	 * @param IUserSession $userSession
63
-	 * @param ISession $session
64
-	 * @param IURLGenerator $urlGenerator
65
-	 */
66
-	public function __construct($appName, IRequest $request, Manager $twoFactorManager, IUserSession $userSession,
67
-		ISession $session, IURLGenerator $urlGenerator) {
68
-		parent::__construct($appName, $request);
69
-		$this->twoFactorManager = $twoFactorManager;
70
-		$this->userSession = $userSession;
71
-		$this->session = $session;
72
-		$this->urlGenerator = $urlGenerator;
73
-	}
58
+    /**
59
+     * @param string $appName
60
+     * @param IRequest $request
61
+     * @param Manager $twoFactorManager
62
+     * @param IUserSession $userSession
63
+     * @param ISession $session
64
+     * @param IURLGenerator $urlGenerator
65
+     */
66
+    public function __construct($appName, IRequest $request, Manager $twoFactorManager, IUserSession $userSession,
67
+        ISession $session, IURLGenerator $urlGenerator) {
68
+        parent::__construct($appName, $request);
69
+        $this->twoFactorManager = $twoFactorManager;
70
+        $this->userSession = $userSession;
71
+        $this->session = $session;
72
+        $this->urlGenerator = $urlGenerator;
73
+    }
74 74
 
75
-	/**
76
-	 * @return string
77
-	 */
78
-	protected function getLogoutUrl() {
79
-		return OC_User::getLogoutUrl($this->urlGenerator);
80
-	}
75
+    /**
76
+     * @return string
77
+     */
78
+    protected function getLogoutUrl() {
79
+        return OC_User::getLogoutUrl($this->urlGenerator);
80
+    }
81 81
 	
82
-	/**
83
-	 * @param IProvider[] $providers
84
-	 */
85
-	private function splitProvidersAndBackupCodes(array $providers): array {
86
-		$regular = [];
87
-		$backup = null;
88
-		foreach ($providers as $provider) {
89
-			if ($provider->getId() === 'backup_codes') {
90
-				$backup = $provider;
91
-			} else {
92
-				$regular[] = $provider;
93
-			}
94
-		}
82
+    /**
83
+     * @param IProvider[] $providers
84
+     */
85
+    private function splitProvidersAndBackupCodes(array $providers): array {
86
+        $regular = [];
87
+        $backup = null;
88
+        foreach ($providers as $provider) {
89
+            if ($provider->getId() === 'backup_codes') {
90
+                $backup = $provider;
91
+            } else {
92
+                $regular[] = $provider;
93
+            }
94
+        }
95 95
 
96
-		return [$regular, $backup];
97
-	}
96
+        return [$regular, $backup];
97
+    }
98 98
 
99
-	/**
100
-	 * @NoAdminRequired
101
-	 * @NoCSRFRequired
102
-	 *
103
-	 * @param string $redirect_url
104
-	 * @return StandaloneTemplateResponse
105
-	 */
106
-	public function selectChallenge($redirect_url) {
107
-		$user = $this->userSession->getUser();
108
-		$providerSet = $this->twoFactorManager->getProviderSet($user);
109
-		$allProviders = $providerSet->getProviders();
110
-		list($providers, $backupProvider) = $this->splitProvidersAndBackupCodes($allProviders);
111
-		$setupProviders = $this->twoFactorManager->getLoginSetupProviders($user);
99
+    /**
100
+     * @NoAdminRequired
101
+     * @NoCSRFRequired
102
+     *
103
+     * @param string $redirect_url
104
+     * @return StandaloneTemplateResponse
105
+     */
106
+    public function selectChallenge($redirect_url) {
107
+        $user = $this->userSession->getUser();
108
+        $providerSet = $this->twoFactorManager->getProviderSet($user);
109
+        $allProviders = $providerSet->getProviders();
110
+        list($providers, $backupProvider) = $this->splitProvidersAndBackupCodes($allProviders);
111
+        $setupProviders = $this->twoFactorManager->getLoginSetupProviders($user);
112 112
 
113
-		$data = [
114
-			'providers' => $providers,
115
-			'backupProvider' => $backupProvider,
116
-			'providerMissing' => $providerSet->isProviderMissing(),
117
-			'redirect_url' => $redirect_url,
118
-			'logout_url' => $this->getLogoutUrl(),
119
-			'hasSetupProviders' => !empty($setupProviders),
120
-		];
121
-		return new StandaloneTemplateResponse($this->appName, 'twofactorselectchallenge', $data, 'guest');
122
-	}
113
+        $data = [
114
+            'providers' => $providers,
115
+            'backupProvider' => $backupProvider,
116
+            'providerMissing' => $providerSet->isProviderMissing(),
117
+            'redirect_url' => $redirect_url,
118
+            'logout_url' => $this->getLogoutUrl(),
119
+            'hasSetupProviders' => !empty($setupProviders),
120
+        ];
121
+        return new StandaloneTemplateResponse($this->appName, 'twofactorselectchallenge', $data, 'guest');
122
+    }
123 123
 
124
-	/**
125
-	 * @NoAdminRequired
126
-	 * @NoCSRFRequired
127
-	 * @UseSession
128
-	 *
129
-	 * @param string $challengeProviderId
130
-	 * @param string $redirect_url
131
-	 * @return StandaloneTemplateResponse|RedirectResponse
132
-	 */
133
-	public function showChallenge($challengeProviderId, $redirect_url) {
134
-		$user = $this->userSession->getUser();
135
-		$providerSet = $this->twoFactorManager->getProviderSet($user);
136
-		$provider = $providerSet->getProvider($challengeProviderId);
124
+    /**
125
+     * @NoAdminRequired
126
+     * @NoCSRFRequired
127
+     * @UseSession
128
+     *
129
+     * @param string $challengeProviderId
130
+     * @param string $redirect_url
131
+     * @return StandaloneTemplateResponse|RedirectResponse
132
+     */
133
+    public function showChallenge($challengeProviderId, $redirect_url) {
134
+        $user = $this->userSession->getUser();
135
+        $providerSet = $this->twoFactorManager->getProviderSet($user);
136
+        $provider = $providerSet->getProvider($challengeProviderId);
137 137
 
138
-		if (is_null($provider)) {
139
-			return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.selectChallenge'));
140
-		}
138
+        if (is_null($provider)) {
139
+            return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.selectChallenge'));
140
+        }
141 141
 
142
-		$backupProvider = $providerSet->getProvider('backup_codes');
143
-		if (!is_null($backupProvider) && $backupProvider->getId() === $provider->getId()) {
144
-			// Don't show the backup provider link if we're already showing that provider's challenge
145
-			$backupProvider = null;
146
-		}
142
+        $backupProvider = $providerSet->getProvider('backup_codes');
143
+        if (!is_null($backupProvider) && $backupProvider->getId() === $provider->getId()) {
144
+            // Don't show the backup provider link if we're already showing that provider's challenge
145
+            $backupProvider = null;
146
+        }
147 147
 
148
-		$errorMessage = '';
149
-		$error = false;
150
-		if ($this->session->exists('two_factor_auth_error')) {
151
-			$this->session->remove('two_factor_auth_error');
152
-			$error = true;
153
-			$errorMessage = $this->session->get("two_factor_auth_error_message");
154
-			$this->session->remove('two_factor_auth_error_message');
155
-		}
156
-		$tmpl = $provider->getTemplate($user);
157
-		$tmpl->assign('redirect_url', $redirect_url);
158
-		$data = [
159
-			'error' => $error,
160
-			'error_message' => $errorMessage,
161
-			'provider' => $provider,
162
-			'backupProvider' => $backupProvider,
163
-			'logout_url' => $this->getLogoutUrl(),
164
-			'redirect_url' => $redirect_url,
165
-			'template' => $tmpl->fetchPage(),
166
-		];
167
-		$response = new StandaloneTemplateResponse($this->appName, 'twofactorshowchallenge', $data, 'guest');
168
-		if ($provider instanceof IProvidesCustomCSP) {
169
-			$response->setContentSecurityPolicy($provider->getCSP());
170
-		}
171
-		return $response;
172
-	}
148
+        $errorMessage = '';
149
+        $error = false;
150
+        if ($this->session->exists('two_factor_auth_error')) {
151
+            $this->session->remove('two_factor_auth_error');
152
+            $error = true;
153
+            $errorMessage = $this->session->get("two_factor_auth_error_message");
154
+            $this->session->remove('two_factor_auth_error_message');
155
+        }
156
+        $tmpl = $provider->getTemplate($user);
157
+        $tmpl->assign('redirect_url', $redirect_url);
158
+        $data = [
159
+            'error' => $error,
160
+            'error_message' => $errorMessage,
161
+            'provider' => $provider,
162
+            'backupProvider' => $backupProvider,
163
+            'logout_url' => $this->getLogoutUrl(),
164
+            'redirect_url' => $redirect_url,
165
+            'template' => $tmpl->fetchPage(),
166
+        ];
167
+        $response = new StandaloneTemplateResponse($this->appName, 'twofactorshowchallenge', $data, 'guest');
168
+        if ($provider instanceof IProvidesCustomCSP) {
169
+            $response->setContentSecurityPolicy($provider->getCSP());
170
+        }
171
+        return $response;
172
+    }
173 173
 
174
-	/**
175
-	 * @NoAdminRequired
176
-	 * @NoCSRFRequired
177
-	 * @UseSession
178
-	 *
179
-	 * @UserRateThrottle(limit=5, period=100)
180
-	 *
181
-	 * @param string $challengeProviderId
182
-	 * @param string $challenge
183
-	 * @param string $redirect_url
184
-	 * @return RedirectResponse
185
-	 */
186
-	public function solveChallenge($challengeProviderId, $challenge, $redirect_url = null) {
187
-		$user = $this->userSession->getUser();
188
-		$provider = $this->twoFactorManager->getProvider($user, $challengeProviderId);
189
-		if (is_null($provider)) {
190
-			return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.selectChallenge'));
191
-		}
174
+    /**
175
+     * @NoAdminRequired
176
+     * @NoCSRFRequired
177
+     * @UseSession
178
+     *
179
+     * @UserRateThrottle(limit=5, period=100)
180
+     *
181
+     * @param string $challengeProviderId
182
+     * @param string $challenge
183
+     * @param string $redirect_url
184
+     * @return RedirectResponse
185
+     */
186
+    public function solveChallenge($challengeProviderId, $challenge, $redirect_url = null) {
187
+        $user = $this->userSession->getUser();
188
+        $provider = $this->twoFactorManager->getProvider($user, $challengeProviderId);
189
+        if (is_null($provider)) {
190
+            return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.selectChallenge'));
191
+        }
192 192
 
193
-		try {
194
-			if ($this->twoFactorManager->verifyChallenge($challengeProviderId, $user, $challenge)) {
195
-				if (!is_null($redirect_url)) {
196
-					return new RedirectResponse($this->urlGenerator->getAbsoluteURL(urldecode($redirect_url)));
197
-				}
198
-				return new RedirectResponse(OC_Util::getDefaultPageUrl());
199
-			}
200
-		} catch (TwoFactorException $e) {
201
-			/*
193
+        try {
194
+            if ($this->twoFactorManager->verifyChallenge($challengeProviderId, $user, $challenge)) {
195
+                if (!is_null($redirect_url)) {
196
+                    return new RedirectResponse($this->urlGenerator->getAbsoluteURL(urldecode($redirect_url)));
197
+                }
198
+                return new RedirectResponse(OC_Util::getDefaultPageUrl());
199
+            }
200
+        } catch (TwoFactorException $e) {
201
+            /*
202 202
 			 * The 2FA App threw an TwoFactorException. Now we display more
203 203
 			 * information to the user. The exception text is stored in the
204 204
 			 * session to be used in showChallenge()
205 205
 			 */
206
-			$this->session->set('two_factor_auth_error_message', $e->getMessage());
207
-		}
206
+            $this->session->set('two_factor_auth_error_message', $e->getMessage());
207
+        }
208 208
 
209
-		$this->session->set('two_factor_auth_error', true);
210
-		return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.showChallenge', [
211
-			'challengeProviderId' => $provider->getId(),
212
-			'redirect_url' => $redirect_url,
213
-		]));
214
-	}
209
+        $this->session->set('two_factor_auth_error', true);
210
+        return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.showChallenge', [
211
+            'challengeProviderId' => $provider->getId(),
212
+            'redirect_url' => $redirect_url,
213
+        ]));
214
+    }
215 215
 
216
-	/**
217
-	 * @NoAdminRequired
218
-	 * @NoCSRFRequired
219
-	 */
220
-	public function setupProviders() {
221
-		$user = $this->userSession->getUser();
222
-		$setupProviders = $this->twoFactorManager->getLoginSetupProviders($user);
216
+    /**
217
+     * @NoAdminRequired
218
+     * @NoCSRFRequired
219
+     */
220
+    public function setupProviders() {
221
+        $user = $this->userSession->getUser();
222
+        $setupProviders = $this->twoFactorManager->getLoginSetupProviders($user);
223 223
 
224
-		$data = [
225
-			'providers' => $setupProviders,
226
-			'logout_url' => $this->getLogoutUrl(),
227
-		];
224
+        $data = [
225
+            'providers' => $setupProviders,
226
+            'logout_url' => $this->getLogoutUrl(),
227
+        ];
228 228
 
229
-		$response = new StandaloneTemplateResponse($this->appName, 'twofactorsetupselection', $data, 'guest');
230
-		return $response;
231
-	}
229
+        $response = new StandaloneTemplateResponse($this->appName, 'twofactorsetupselection', $data, 'guest');
230
+        return $response;
231
+    }
232 232
 
233
-	/**
234
-	 * @NoAdminRequired
235
-	 * @NoCSRFRequired
236
-	 */
237
-	public function setupProvider(string $providerId) {
238
-		$user = $this->userSession->getUser();
239
-		$providers = $this->twoFactorManager->getLoginSetupProviders($user);
233
+    /**
234
+     * @NoAdminRequired
235
+     * @NoCSRFRequired
236
+     */
237
+    public function setupProvider(string $providerId) {
238
+        $user = $this->userSession->getUser();
239
+        $providers = $this->twoFactorManager->getLoginSetupProviders($user);
240 240
 
241
-		$provider = null;
242
-		foreach ($providers as $p) {
243
-			if ($p->getId() === $providerId) {
244
-				$provider = $p;
245
-				break;
246
-			}
247
-		}
241
+        $provider = null;
242
+        foreach ($providers as $p) {
243
+            if ($p->getId() === $providerId) {
244
+                $provider = $p;
245
+                break;
246
+            }
247
+        }
248 248
 
249
-		if ($provider === null) {
250
-			return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.selectChallenge'));
251
-		}
249
+        if ($provider === null) {
250
+            return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.selectChallenge'));
251
+        }
252 252
 
253
-		/** @var IActivatableAtLogin $provider */
254
-		$tmpl = $provider->getLoginSetup($user)->getBody();
255
-		$data = [
256
-			'provider' => $provider,
257
-			'logout_url' => $this->getLogoutUrl(),
258
-			'template' => $tmpl->fetchPage(),
259
-		];
260
-		$response = new StandaloneTemplateResponse($this->appName, 'twofactorsetupchallenge', $data, 'guest');
261
-		return $response;
262
-	}
253
+        /** @var IActivatableAtLogin $provider */
254
+        $tmpl = $provider->getLoginSetup($user)->getBody();
255
+        $data = [
256
+            'provider' => $provider,
257
+            'logout_url' => $this->getLogoutUrl(),
258
+            'template' => $tmpl->fetchPage(),
259
+        ];
260
+        $response = new StandaloneTemplateResponse($this->appName, 'twofactorsetupchallenge', $data, 'guest');
261
+        return $response;
262
+    }
263 263
 
264
-	/**
265
-	 * @NoAdminRequired
266
-	 * @NoCSRFRequired
267
-	 *
268
-	 * @todo handle the extreme edge case of an invalid provider ID and redirect to the provider selection page
269
-	 */
270
-	public function confirmProviderSetup(string $providerId) {
271
-		return new RedirectResponse($this->urlGenerator->linkToRoute(
272
-			'core.TwoFactorChallenge.showChallenge',
273
-			[
274
-				'challengeProviderId' => $providerId,
275
-			]
276
-		));
277
-	}
264
+    /**
265
+     * @NoAdminRequired
266
+     * @NoCSRFRequired
267
+     *
268
+     * @todo handle the extreme edge case of an invalid provider ID and redirect to the provider selection page
269
+     */
270
+    public function confirmProviderSetup(string $providerId) {
271
+        return new RedirectResponse($this->urlGenerator->linkToRoute(
272
+            'core.TwoFactorChallenge.showChallenge',
273
+            [
274
+                'challengeProviderId' => $providerId,
275
+            ]
276
+        ));
277
+    }
278 278
 
279 279
 }
Please login to merge, or discard this patch.
lib/public/Authentication/TwoFactorAuth/IActivatableAtLogin.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -31,13 +31,13 @@
 block discarded – undo
31 31
  */
32 32
 interface IActivatableAtLogin extends IProvider {
33 33
 
34
-	/**
35
-	 * @param IUser $user
36
-	 *
37
-	 * @return ILoginSetupProvider
38
-	 *
39
-	 * @since 17.0.0
40
-	 */
41
-	public function getLoginSetup(IUser $user): ILoginSetupProvider;
34
+    /**
35
+     * @param IUser $user
36
+     *
37
+     * @return ILoginSetupProvider
38
+     *
39
+     * @since 17.0.0
40
+     */
41
+    public function getLoginSetup(IUser $user): ILoginSetupProvider;
42 42
 
43 43
 }
Please login to merge, or discard this patch.
lib/public/Authentication/TwoFactorAuth/ILoginSetupProvider.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -31,11 +31,11 @@
 block discarded – undo
31 31
  */
32 32
 interface ILoginSetupProvider {
33 33
 
34
-	/**
35
-	 * @return Template
36
-	 *
37
-	 * @since 17.0.0
38
-	 */
39
-	public function getBody(): Template;
34
+    /**
35
+     * @return Template
36
+     *
37
+     * @since 17.0.0
38
+     */
39
+    public function getBody(): Template;
40 40
 
41 41
 }
Please login to merge, or discard this patch.
lib/private/Authentication/TwoFactorAuth/Manager.php 1 patch
Indentation   +334 added lines, -334 removed lines patch added patch discarded remove patch
@@ -49,342 +49,342 @@
 block discarded – undo
49 49
 
50 50
 class Manager {
51 51
 
52
-	const SESSION_UID_KEY = 'two_factor_auth_uid';
53
-	const SESSION_UID_DONE = 'two_factor_auth_passed';
54
-	const REMEMBER_LOGIN = 'two_factor_remember_login';
55
-	const BACKUP_CODES_PROVIDER_ID = 'backup_codes';
56
-
57
-	/** @var ProviderLoader */
58
-	private $providerLoader;
59
-
60
-	/** @var IRegistry */
61
-	private $providerRegistry;
62
-
63
-	/** @var MandatoryTwoFactor */
64
-	private $mandatoryTwoFactor;
65
-
66
-	/** @var ISession */
67
-	private $session;
68
-
69
-	/** @var IConfig */
70
-	private $config;
71
-
72
-	/** @var IManager */
73
-	private $activityManager;
74
-
75
-	/** @var ILogger */
76
-	private $logger;
77
-
78
-	/** @var TokenProvider */
79
-	private $tokenProvider;
80
-
81
-	/** @var ITimeFactory */
82
-	private $timeFactory;
83
-
84
-	/** @var EventDispatcherInterface */
85
-	private $dispatcher;
86
-
87
-	public function __construct(ProviderLoader $providerLoader,
88
-								IRegistry $providerRegistry,
89
-								MandatoryTwoFactor $mandatoryTwoFactor,
90
-								ISession $session, IConfig $config,
91
-								IManager $activityManager, ILogger $logger, TokenProvider $tokenProvider,
92
-								ITimeFactory $timeFactory, EventDispatcherInterface $eventDispatcher) {
93
-		$this->providerLoader = $providerLoader;
94
-		$this->providerRegistry = $providerRegistry;
95
-		$this->mandatoryTwoFactor = $mandatoryTwoFactor;
96
-		$this->session = $session;
97
-		$this->config = $config;
98
-		$this->activityManager = $activityManager;
99
-		$this->logger = $logger;
100
-		$this->tokenProvider = $tokenProvider;
101
-		$this->timeFactory = $timeFactory;
102
-		$this->dispatcher = $eventDispatcher;
103
-	}
104
-
105
-	/**
106
-	 * Determine whether the user must provide a second factor challenge
107
-	 *
108
-	 * @param IUser $user
109
-	 * @return boolean
110
-	 */
111
-	public function isTwoFactorAuthenticated(IUser $user): bool {
112
-		if ($this->mandatoryTwoFactor->isEnforcedFor($user)) {
113
-			return true;
114
-		}
115
-
116
-		$providerStates = $this->providerRegistry->getProviderStates($user);
117
-		$providers = $this->providerLoader->getProviders($user);
118
-		$fixedStates = $this->fixMissingProviderStates($providerStates, $providers, $user);
119
-		$enabled = array_filter($fixedStates);
120
-		$providerIds = array_keys($enabled);
121
-		$providerIdsWithoutBackupCodes = array_diff($providerIds, [self::BACKUP_CODES_PROVIDER_ID]);
122
-
123
-		return !empty($providerIdsWithoutBackupCodes);
124
-	}
125
-
126
-	/**
127
-	 * Get a 2FA provider by its ID
128
-	 *
129
-	 * @param IUser $user
130
-	 * @param string $challengeProviderId
131
-	 * @return IProvider|null
132
-	 */
133
-	public function getProvider(IUser $user, string $challengeProviderId) {
134
-		$providers = $this->getProviderSet($user)->getProviders();
135
-		return $providers[$challengeProviderId] ?? null;
136
-	}
137
-
138
-	/**
139
-	 * @param IUser $user
140
-	 * @return IActivatableAtLogin[]
141
-	 * @throws Exception
142
-	 */
143
-	public function getLoginSetupProviders(IUser $user): array {
144
-		$providers = $this->providerLoader->getProviders($user);
145
-		return array_filter($providers, function(IProvider $provider) {
146
-			return ($provider instanceof IActivatableAtLogin);
147
-		});
148
-	}
149
-
150
-	/**
151
-	 * Check if the persistant mapping of enabled/disabled state of each available
152
-	 * provider is missing an entry and add it to the registry in that case.
153
-	 *
154
-	 * @todo remove in Nextcloud 17 as by then all providers should have been updated
155
-	 *
156
-	 * @param string[] $providerStates
157
-	 * @param IProvider[] $providers
158
-	 * @param IUser $user
159
-	 * @return string[] the updated $providerStates variable
160
-	 */
161
-	private function fixMissingProviderStates(array $providerStates,
162
-		array $providers, IUser $user): array {
163
-
164
-		foreach ($providers as $provider) {
165
-			if (isset($providerStates[$provider->getId()])) {
166
-				// All good
167
-				continue;
168
-			}
169
-
170
-			$enabled = $provider->isTwoFactorAuthEnabledForUser($user);
171
-			if ($enabled) {
172
-				$this->providerRegistry->enableProviderFor($provider, $user);
173
-			} else {
174
-				$this->providerRegistry->disableProviderFor($provider, $user);
175
-			}
176
-			$providerStates[$provider->getId()] = $enabled;
177
-		}
178
-
179
-		return $providerStates;
180
-	}
181
-
182
-	/**
183
-	 * @param array $states
184
-	 * @param IProvider $providers
185
-	 */
186
-	private function isProviderMissing(array $states, array $providers): bool {
187
-		$indexed = [];
188
-		foreach ($providers as $provider) {
189
-			$indexed[$provider->getId()] = $provider;
190
-		}
191
-
192
-		$missing = [];
193
-		foreach ($states as $providerId => $enabled) {
194
-			if (!$enabled) {
195
-				// Don't care
196
-				continue;
197
-			}
198
-
199
-			if (!isset($indexed[$providerId])) {
200
-				$missing[] = $providerId;
201
-				$this->logger->alert("two-factor auth provider '$providerId' failed to load",
202
-					[
203
-					'app' => 'core',
204
-				]);
205
-			}
206
-		}
207
-
208
-		if (!empty($missing)) {
209
-			// There was at least one provider missing
210
-			$this->logger->alert(count($missing) . " two-factor auth providers failed to load", ['app' => 'core']);
211
-
212
-			return true;
213
-		}
214
-
215
-		// If we reach this, there was not a single provider missing
216
-		return false;
217
-	}
218
-
219
-	/**
220
-	 * Get the list of 2FA providers for the given user
221
-	 *
222
-	 * @param IUser $user
223
-	 * @throws Exception
224
-	 */
225
-	public function getProviderSet(IUser $user): ProviderSet {
226
-		$providerStates = $this->providerRegistry->getProviderStates($user);
227
-		$providers = $this->providerLoader->getProviders($user);
228
-
229
-		$fixedStates = $this->fixMissingProviderStates($providerStates, $providers, $user);
230
-		$isProviderMissing = $this->isProviderMissing($fixedStates, $providers);
231
-
232
-		$enabled = array_filter($providers, function (IProvider $provider) use ($fixedStates) {
233
-			return $fixedStates[$provider->getId()];
234
-		});
235
-		return new ProviderSet($enabled, $isProviderMissing);
236
-	}
237
-
238
-	/**
239
-	 * Verify the given challenge
240
-	 *
241
-	 * @param string $providerId
242
-	 * @param IUser $user
243
-	 * @param string $challenge
244
-	 * @return boolean
245
-	 */
246
-	public function verifyChallenge(string $providerId, IUser $user, string $challenge): bool {
247
-		$provider = $this->getProvider($user, $providerId);
248
-		if ($provider === null) {
249
-			return false;
250
-		}
251
-
252
-		$passed = $provider->verifyChallenge($user, $challenge);
253
-		if ($passed) {
254
-			if ($this->session->get(self::REMEMBER_LOGIN) === true) {
255
-				// TODO: resolve cyclic dependency and use DI
256
-				\OC::$server->getUserSession()->createRememberMeToken($user);
257
-			}
258
-			$this->session->remove(self::SESSION_UID_KEY);
259
-			$this->session->remove(self::REMEMBER_LOGIN);
260
-			$this->session->set(self::SESSION_UID_DONE, $user->getUID());
261
-
262
-			// Clear token from db
263
-			$sessionId = $this->session->getId();
264
-			$token = $this->tokenProvider->getToken($sessionId);
265
-			$tokenId = $token->getId();
266
-			$this->config->deleteUserValue($user->getUID(), 'login_token_2fa', $tokenId);
267
-
268
-			$dispatchEvent = new GenericEvent($user, ['provider' => $provider->getDisplayName()]);
269
-			$this->dispatcher->dispatch(IProvider::EVENT_SUCCESS, $dispatchEvent);
270
-
271
-			$this->publishEvent($user, 'twofactor_success', [
272
-				'provider' => $provider->getDisplayName(),
273
-			]);
274
-		} else {
275
-			$dispatchEvent = new GenericEvent($user, ['provider' => $provider->getDisplayName()]);
276
-			$this->dispatcher->dispatch(IProvider::EVENT_FAILED, $dispatchEvent);
277
-
278
-			$this->publishEvent($user, 'twofactor_failed', [
279
-				'provider' => $provider->getDisplayName(),
280
-			]);
281
-		}
282
-		return $passed;
283
-	}
284
-
285
-	/**
286
-	 * Push a 2fa event the user's activity stream
287
-	 *
288
-	 * @param IUser $user
289
-	 * @param string $event
290
-	 * @param array $params
291
-	 */
292
-	private function publishEvent(IUser $user, string $event, array $params) {
293
-		$activity = $this->activityManager->generateEvent();
294
-		$activity->setApp('core')
295
-			->setType('security')
296
-			->setAuthor($user->getUID())
297
-			->setAffectedUser($user->getUID())
298
-			->setSubject($event, $params);
299
-		try {
300
-			$this->activityManager->publish($activity);
301
-		} catch (BadMethodCallException $e) {
302
-			$this->logger->warning('could not publish activity', ['app' => 'core']);
303
-			$this->logger->logException($e, ['app' => 'core']);
304
-		}
305
-	}
306
-
307
-	/**
308
-	 * Check if the currently logged in user needs to pass 2FA
309
-	 *
310
-	 * @param IUser $user the currently logged in user
311
-	 * @return boolean
312
-	 */
313
-	public function needsSecondFactor(IUser $user = null): bool {
314
-		if ($user === null) {
315
-			return false;
316
-		}
317
-
318
-		// If we are authenticated using an app password skip all this
319
-		if ($this->session->exists('app_password')) {
320
-			return false;
321
-		}
322
-
323
-		// First check if the session tells us we should do 2FA (99% case)
324
-		if (!$this->session->exists(self::SESSION_UID_KEY)) {
325
-
326
-			// Check if the session tells us it is 2FA authenticated already
327
-			if ($this->session->exists(self::SESSION_UID_DONE) &&
328
-				$this->session->get(self::SESSION_UID_DONE) === $user->getUID()) {
329
-				return false;
330
-			}
331
-
332
-			/*
52
+    const SESSION_UID_KEY = 'two_factor_auth_uid';
53
+    const SESSION_UID_DONE = 'two_factor_auth_passed';
54
+    const REMEMBER_LOGIN = 'two_factor_remember_login';
55
+    const BACKUP_CODES_PROVIDER_ID = 'backup_codes';
56
+
57
+    /** @var ProviderLoader */
58
+    private $providerLoader;
59
+
60
+    /** @var IRegistry */
61
+    private $providerRegistry;
62
+
63
+    /** @var MandatoryTwoFactor */
64
+    private $mandatoryTwoFactor;
65
+
66
+    /** @var ISession */
67
+    private $session;
68
+
69
+    /** @var IConfig */
70
+    private $config;
71
+
72
+    /** @var IManager */
73
+    private $activityManager;
74
+
75
+    /** @var ILogger */
76
+    private $logger;
77
+
78
+    /** @var TokenProvider */
79
+    private $tokenProvider;
80
+
81
+    /** @var ITimeFactory */
82
+    private $timeFactory;
83
+
84
+    /** @var EventDispatcherInterface */
85
+    private $dispatcher;
86
+
87
+    public function __construct(ProviderLoader $providerLoader,
88
+                                IRegistry $providerRegistry,
89
+                                MandatoryTwoFactor $mandatoryTwoFactor,
90
+                                ISession $session, IConfig $config,
91
+                                IManager $activityManager, ILogger $logger, TokenProvider $tokenProvider,
92
+                                ITimeFactory $timeFactory, EventDispatcherInterface $eventDispatcher) {
93
+        $this->providerLoader = $providerLoader;
94
+        $this->providerRegistry = $providerRegistry;
95
+        $this->mandatoryTwoFactor = $mandatoryTwoFactor;
96
+        $this->session = $session;
97
+        $this->config = $config;
98
+        $this->activityManager = $activityManager;
99
+        $this->logger = $logger;
100
+        $this->tokenProvider = $tokenProvider;
101
+        $this->timeFactory = $timeFactory;
102
+        $this->dispatcher = $eventDispatcher;
103
+    }
104
+
105
+    /**
106
+     * Determine whether the user must provide a second factor challenge
107
+     *
108
+     * @param IUser $user
109
+     * @return boolean
110
+     */
111
+    public function isTwoFactorAuthenticated(IUser $user): bool {
112
+        if ($this->mandatoryTwoFactor->isEnforcedFor($user)) {
113
+            return true;
114
+        }
115
+
116
+        $providerStates = $this->providerRegistry->getProviderStates($user);
117
+        $providers = $this->providerLoader->getProviders($user);
118
+        $fixedStates = $this->fixMissingProviderStates($providerStates, $providers, $user);
119
+        $enabled = array_filter($fixedStates);
120
+        $providerIds = array_keys($enabled);
121
+        $providerIdsWithoutBackupCodes = array_diff($providerIds, [self::BACKUP_CODES_PROVIDER_ID]);
122
+
123
+        return !empty($providerIdsWithoutBackupCodes);
124
+    }
125
+
126
+    /**
127
+     * Get a 2FA provider by its ID
128
+     *
129
+     * @param IUser $user
130
+     * @param string $challengeProviderId
131
+     * @return IProvider|null
132
+     */
133
+    public function getProvider(IUser $user, string $challengeProviderId) {
134
+        $providers = $this->getProviderSet($user)->getProviders();
135
+        return $providers[$challengeProviderId] ?? null;
136
+    }
137
+
138
+    /**
139
+     * @param IUser $user
140
+     * @return IActivatableAtLogin[]
141
+     * @throws Exception
142
+     */
143
+    public function getLoginSetupProviders(IUser $user): array {
144
+        $providers = $this->providerLoader->getProviders($user);
145
+        return array_filter($providers, function(IProvider $provider) {
146
+            return ($provider instanceof IActivatableAtLogin);
147
+        });
148
+    }
149
+
150
+    /**
151
+     * Check if the persistant mapping of enabled/disabled state of each available
152
+     * provider is missing an entry and add it to the registry in that case.
153
+     *
154
+     * @todo remove in Nextcloud 17 as by then all providers should have been updated
155
+     *
156
+     * @param string[] $providerStates
157
+     * @param IProvider[] $providers
158
+     * @param IUser $user
159
+     * @return string[] the updated $providerStates variable
160
+     */
161
+    private function fixMissingProviderStates(array $providerStates,
162
+        array $providers, IUser $user): array {
163
+
164
+        foreach ($providers as $provider) {
165
+            if (isset($providerStates[$provider->getId()])) {
166
+                // All good
167
+                continue;
168
+            }
169
+
170
+            $enabled = $provider->isTwoFactorAuthEnabledForUser($user);
171
+            if ($enabled) {
172
+                $this->providerRegistry->enableProviderFor($provider, $user);
173
+            } else {
174
+                $this->providerRegistry->disableProviderFor($provider, $user);
175
+            }
176
+            $providerStates[$provider->getId()] = $enabled;
177
+        }
178
+
179
+        return $providerStates;
180
+    }
181
+
182
+    /**
183
+     * @param array $states
184
+     * @param IProvider $providers
185
+     */
186
+    private function isProviderMissing(array $states, array $providers): bool {
187
+        $indexed = [];
188
+        foreach ($providers as $provider) {
189
+            $indexed[$provider->getId()] = $provider;
190
+        }
191
+
192
+        $missing = [];
193
+        foreach ($states as $providerId => $enabled) {
194
+            if (!$enabled) {
195
+                // Don't care
196
+                continue;
197
+            }
198
+
199
+            if (!isset($indexed[$providerId])) {
200
+                $missing[] = $providerId;
201
+                $this->logger->alert("two-factor auth provider '$providerId' failed to load",
202
+                    [
203
+                    'app' => 'core',
204
+                ]);
205
+            }
206
+        }
207
+
208
+        if (!empty($missing)) {
209
+            // There was at least one provider missing
210
+            $this->logger->alert(count($missing) . " two-factor auth providers failed to load", ['app' => 'core']);
211
+
212
+            return true;
213
+        }
214
+
215
+        // If we reach this, there was not a single provider missing
216
+        return false;
217
+    }
218
+
219
+    /**
220
+     * Get the list of 2FA providers for the given user
221
+     *
222
+     * @param IUser $user
223
+     * @throws Exception
224
+     */
225
+    public function getProviderSet(IUser $user): ProviderSet {
226
+        $providerStates = $this->providerRegistry->getProviderStates($user);
227
+        $providers = $this->providerLoader->getProviders($user);
228
+
229
+        $fixedStates = $this->fixMissingProviderStates($providerStates, $providers, $user);
230
+        $isProviderMissing = $this->isProviderMissing($fixedStates, $providers);
231
+
232
+        $enabled = array_filter($providers, function (IProvider $provider) use ($fixedStates) {
233
+            return $fixedStates[$provider->getId()];
234
+        });
235
+        return new ProviderSet($enabled, $isProviderMissing);
236
+    }
237
+
238
+    /**
239
+     * Verify the given challenge
240
+     *
241
+     * @param string $providerId
242
+     * @param IUser $user
243
+     * @param string $challenge
244
+     * @return boolean
245
+     */
246
+    public function verifyChallenge(string $providerId, IUser $user, string $challenge): bool {
247
+        $provider = $this->getProvider($user, $providerId);
248
+        if ($provider === null) {
249
+            return false;
250
+        }
251
+
252
+        $passed = $provider->verifyChallenge($user, $challenge);
253
+        if ($passed) {
254
+            if ($this->session->get(self::REMEMBER_LOGIN) === true) {
255
+                // TODO: resolve cyclic dependency and use DI
256
+                \OC::$server->getUserSession()->createRememberMeToken($user);
257
+            }
258
+            $this->session->remove(self::SESSION_UID_KEY);
259
+            $this->session->remove(self::REMEMBER_LOGIN);
260
+            $this->session->set(self::SESSION_UID_DONE, $user->getUID());
261
+
262
+            // Clear token from db
263
+            $sessionId = $this->session->getId();
264
+            $token = $this->tokenProvider->getToken($sessionId);
265
+            $tokenId = $token->getId();
266
+            $this->config->deleteUserValue($user->getUID(), 'login_token_2fa', $tokenId);
267
+
268
+            $dispatchEvent = new GenericEvent($user, ['provider' => $provider->getDisplayName()]);
269
+            $this->dispatcher->dispatch(IProvider::EVENT_SUCCESS, $dispatchEvent);
270
+
271
+            $this->publishEvent($user, 'twofactor_success', [
272
+                'provider' => $provider->getDisplayName(),
273
+            ]);
274
+        } else {
275
+            $dispatchEvent = new GenericEvent($user, ['provider' => $provider->getDisplayName()]);
276
+            $this->dispatcher->dispatch(IProvider::EVENT_FAILED, $dispatchEvent);
277
+
278
+            $this->publishEvent($user, 'twofactor_failed', [
279
+                'provider' => $provider->getDisplayName(),
280
+            ]);
281
+        }
282
+        return $passed;
283
+    }
284
+
285
+    /**
286
+     * Push a 2fa event the user's activity stream
287
+     *
288
+     * @param IUser $user
289
+     * @param string $event
290
+     * @param array $params
291
+     */
292
+    private function publishEvent(IUser $user, string $event, array $params) {
293
+        $activity = $this->activityManager->generateEvent();
294
+        $activity->setApp('core')
295
+            ->setType('security')
296
+            ->setAuthor($user->getUID())
297
+            ->setAffectedUser($user->getUID())
298
+            ->setSubject($event, $params);
299
+        try {
300
+            $this->activityManager->publish($activity);
301
+        } catch (BadMethodCallException $e) {
302
+            $this->logger->warning('could not publish activity', ['app' => 'core']);
303
+            $this->logger->logException($e, ['app' => 'core']);
304
+        }
305
+    }
306
+
307
+    /**
308
+     * Check if the currently logged in user needs to pass 2FA
309
+     *
310
+     * @param IUser $user the currently logged in user
311
+     * @return boolean
312
+     */
313
+    public function needsSecondFactor(IUser $user = null): bool {
314
+        if ($user === null) {
315
+            return false;
316
+        }
317
+
318
+        // If we are authenticated using an app password skip all this
319
+        if ($this->session->exists('app_password')) {
320
+            return false;
321
+        }
322
+
323
+        // First check if the session tells us we should do 2FA (99% case)
324
+        if (!$this->session->exists(self::SESSION_UID_KEY)) {
325
+
326
+            // Check if the session tells us it is 2FA authenticated already
327
+            if ($this->session->exists(self::SESSION_UID_DONE) &&
328
+                $this->session->get(self::SESSION_UID_DONE) === $user->getUID()) {
329
+                return false;
330
+            }
331
+
332
+            /*
333 333
 			 * If the session is expired check if we are not logged in by a token
334 334
 			 * that still needs 2FA auth
335 335
 			 */
336
-			try {
337
-				$sessionId = $this->session->getId();
338
-				$token = $this->tokenProvider->getToken($sessionId);
339
-				$tokenId = $token->getId();
340
-				$tokensNeeding2FA = $this->config->getUserKeys($user->getUID(), 'login_token_2fa');
341
-
342
-				if (!\in_array($tokenId, $tokensNeeding2FA, true)) {
343
-					$this->session->set(self::SESSION_UID_DONE, $user->getUID());
344
-					return false;
345
-				}
346
-			} catch (InvalidTokenException $e) {
347
-			}
348
-		}
349
-
350
-		if (!$this->isTwoFactorAuthenticated($user)) {
351
-			// There is no second factor any more -> let the user pass
352
-			//   This prevents infinite redirect loops when a user is about
353
-			//   to solve the 2FA challenge, and the provider app is
354
-			//   disabled the same time
355
-			$this->session->remove(self::SESSION_UID_KEY);
356
-
357
-			$keys = $this->config->getUserKeys($user->getUID(), 'login_token_2fa');
358
-			foreach ($keys as $key) {
359
-				$this->config->deleteUserValue($user->getUID(), 'login_token_2fa', $key);
360
-			}
361
-			return false;
362
-		}
363
-
364
-		return true;
365
-	}
366
-
367
-	/**
368
-	 * Prepare the 2FA login
369
-	 *
370
-	 * @param IUser $user
371
-	 * @param boolean $rememberMe
372
-	 */
373
-	public function prepareTwoFactorLogin(IUser $user, bool $rememberMe) {
374
-		$this->session->set(self::SESSION_UID_KEY, $user->getUID());
375
-		$this->session->set(self::REMEMBER_LOGIN, $rememberMe);
376
-
377
-		$id = $this->session->getId();
378
-		$token = $this->tokenProvider->getToken($id);
379
-		$this->config->setUserValue($user->getUID(), 'login_token_2fa', $token->getId(), $this->timeFactory->getTime());
380
-	}
381
-
382
-	public function clearTwoFactorPending(string $userId) {
383
-		$tokensNeeding2FA = $this->config->getUserKeys($userId, 'login_token_2fa');
384
-
385
-		foreach ($tokensNeeding2FA as $tokenId) {
386
-			$this->tokenProvider->invalidateTokenById($userId, $tokenId);
387
-		}
388
-	}
336
+            try {
337
+                $sessionId = $this->session->getId();
338
+                $token = $this->tokenProvider->getToken($sessionId);
339
+                $tokenId = $token->getId();
340
+                $tokensNeeding2FA = $this->config->getUserKeys($user->getUID(), 'login_token_2fa');
341
+
342
+                if (!\in_array($tokenId, $tokensNeeding2FA, true)) {
343
+                    $this->session->set(self::SESSION_UID_DONE, $user->getUID());
344
+                    return false;
345
+                }
346
+            } catch (InvalidTokenException $e) {
347
+            }
348
+        }
349
+
350
+        if (!$this->isTwoFactorAuthenticated($user)) {
351
+            // There is no second factor any more -> let the user pass
352
+            //   This prevents infinite redirect loops when a user is about
353
+            //   to solve the 2FA challenge, and the provider app is
354
+            //   disabled the same time
355
+            $this->session->remove(self::SESSION_UID_KEY);
356
+
357
+            $keys = $this->config->getUserKeys($user->getUID(), 'login_token_2fa');
358
+            foreach ($keys as $key) {
359
+                $this->config->deleteUserValue($user->getUID(), 'login_token_2fa', $key);
360
+            }
361
+            return false;
362
+        }
363
+
364
+        return true;
365
+    }
366
+
367
+    /**
368
+     * Prepare the 2FA login
369
+     *
370
+     * @param IUser $user
371
+     * @param boolean $rememberMe
372
+     */
373
+    public function prepareTwoFactorLogin(IUser $user, bool $rememberMe) {
374
+        $this->session->set(self::SESSION_UID_KEY, $user->getUID());
375
+        $this->session->set(self::REMEMBER_LOGIN, $rememberMe);
376
+
377
+        $id = $this->session->getId();
378
+        $token = $this->tokenProvider->getToken($id);
379
+        $this->config->setUserValue($user->getUID(), 'login_token_2fa', $token->getId(), $this->timeFactory->getTime());
380
+    }
381
+
382
+    public function clearTwoFactorPending(string $userId) {
383
+        $tokensNeeding2FA = $this->config->getUserKeys($userId, 'login_token_2fa');
384
+
385
+        foreach ($tokensNeeding2FA as $tokenId) {
386
+            $this->tokenProvider->invalidateTokenById($userId, $tokenId);
387
+        }
388
+    }
389 389
 
390 390
 }
Please login to merge, or discard this patch.
lib/private/Authentication/Login/TwoFactorCommand.php 1 patch
Indentation   +48 added lines, -48 removed lines patch added patch discarded remove patch
@@ -34,61 +34,61 @@
 block discarded – undo
34 34
 
35 35
 class TwoFactorCommand extends ALoginCommand {
36 36
 
37
-	/** @var Manager */
38
-	private $twoFactorManager;
37
+    /** @var Manager */
38
+    private $twoFactorManager;
39 39
 
40
-	/** @var MandatoryTwoFactor */
41
-	private $mandatoryTwoFactor;
40
+    /** @var MandatoryTwoFactor */
41
+    private $mandatoryTwoFactor;
42 42
 
43
-	/** @var IURLGenerator */
44
-	private $urlGenerator;
43
+    /** @var IURLGenerator */
44
+    private $urlGenerator;
45 45
 
46
-	public function __construct(Manager $twoFactorManager,
47
-								MandatoryTwoFactor $mandatoryTwoFactor,
48
-								IURLGenerator $urlGenerator) {
49
-		$this->twoFactorManager = $twoFactorManager;
50
-		$this->mandatoryTwoFactor = $mandatoryTwoFactor;
51
-		$this->urlGenerator = $urlGenerator;
52
-	}
46
+    public function __construct(Manager $twoFactorManager,
47
+                                MandatoryTwoFactor $mandatoryTwoFactor,
48
+                                IURLGenerator $urlGenerator) {
49
+        $this->twoFactorManager = $twoFactorManager;
50
+        $this->mandatoryTwoFactor = $mandatoryTwoFactor;
51
+        $this->urlGenerator = $urlGenerator;
52
+    }
53 53
 
54
-	public function process(LoginData $loginData): LoginResult {
55
-		if (!$this->twoFactorManager->isTwoFactorAuthenticated($loginData->getUser())) {
56
-			return $this->processNextOrFinishSuccessfully($loginData);
57
-		}
54
+    public function process(LoginData $loginData): LoginResult {
55
+        if (!$this->twoFactorManager->isTwoFactorAuthenticated($loginData->getUser())) {
56
+            return $this->processNextOrFinishSuccessfully($loginData);
57
+        }
58 58
 
59
-		$this->twoFactorManager->prepareTwoFactorLogin($loginData->getUser(), $loginData->isRememberLogin());
59
+        $this->twoFactorManager->prepareTwoFactorLogin($loginData->getUser(), $loginData->isRememberLogin());
60 60
 
61
-		$providerSet = $this->twoFactorManager->getProviderSet($loginData->getUser());
62
-		$loginProviders = $this->twoFactorManager->getLoginSetupProviders($loginData->getUser());
63
-		$providers = $providerSet->getPrimaryProviders();
64
-		if (empty($providers)
65
-			&& !$providerSet->isProviderMissing()
66
-			&& !empty($loginProviders)
67
-			&& $this->mandatoryTwoFactor->isEnforcedFor($loginData->getUser())) {
68
-			// No providers set up, but 2FA is enforced and setup providers are available
69
-			$url = 'core.TwoFactorChallenge.setupProviders';
70
-			$urlParams = [];
71
-		} else if (!$providerSet->isProviderMissing() && count($providers) === 1) {
72
-			// Single provider (and no missing ones), hence we can redirect to that provider's challenge page directly
73
-			/* @var $provider IProvider */
74
-			$provider = array_pop($providers);
75
-			$url = 'core.TwoFactorChallenge.showChallenge';
76
-			$urlParams = [
77
-				'challengeProviderId' => $provider->getId(),
78
-			];
79
-		} else {
80
-			$url = 'core.TwoFactorChallenge.selectChallenge';
81
-			$urlParams = [];
82
-		}
61
+        $providerSet = $this->twoFactorManager->getProviderSet($loginData->getUser());
62
+        $loginProviders = $this->twoFactorManager->getLoginSetupProviders($loginData->getUser());
63
+        $providers = $providerSet->getPrimaryProviders();
64
+        if (empty($providers)
65
+            && !$providerSet->isProviderMissing()
66
+            && !empty($loginProviders)
67
+            && $this->mandatoryTwoFactor->isEnforcedFor($loginData->getUser())) {
68
+            // No providers set up, but 2FA is enforced and setup providers are available
69
+            $url = 'core.TwoFactorChallenge.setupProviders';
70
+            $urlParams = [];
71
+        } else if (!$providerSet->isProviderMissing() && count($providers) === 1) {
72
+            // Single provider (and no missing ones), hence we can redirect to that provider's challenge page directly
73
+            /* @var $provider IProvider */
74
+            $provider = array_pop($providers);
75
+            $url = 'core.TwoFactorChallenge.showChallenge';
76
+            $urlParams = [
77
+                'challengeProviderId' => $provider->getId(),
78
+            ];
79
+        } else {
80
+            $url = 'core.TwoFactorChallenge.selectChallenge';
81
+            $urlParams = [];
82
+        }
83 83
 
84
-		if ($loginData->getRedirectUrl() !== null) {
85
-			$urlParams['redirect_url'] = $loginData->getRedirectUrl();
86
-		}
84
+        if ($loginData->getRedirectUrl() !== null) {
85
+            $urlParams['redirect_url'] = $loginData->getRedirectUrl();
86
+        }
87 87
 
88
-		return LoginResult::success(
89
-			$loginData,
90
-			$this->urlGenerator->linkToRoute($url, $urlParams)
91
-		);
92
-	}
88
+        return LoginResult::success(
89
+            $loginData,
90
+            $this->urlGenerator->linkToRoute($url, $urlParams)
91
+        );
92
+    }
93 93
 
94 94
 }
Please login to merge, or discard this patch.