3131use OC \Authentication \Events \AppPasswordCreatedEvent ;
3232use OC \Authentication \Token \IProvider ;
3333use OC \Authentication \Token \IToken ;
34+ use OC \User \Session ;
3435use OCP \AppFramework \Http ;
36+ use OCP \AppFramework \Http \Attribute \UseSession ;
3537use OCP \AppFramework \Http \DataResponse ;
3638use OCP \AppFramework \OCS \OCSForbiddenException ;
3739use OCP \Authentication \Exceptions \CredentialsUnavailableException ;
4143use OCP \EventDispatcher \IEventDispatcher ;
4244use OCP \IRequest ;
4345use OCP \ISession ;
46+ use OCP \IUserManager ;
47+ use OCP \Security \Bruteforce \IThrottler ;
4448use OCP \Security \ISecureRandom ;
4549
4650class AppPasswordController extends \OCP \AppFramework \OCSController {
@@ -52,6 +56,9 @@ public function __construct(
5256 private IProvider $ tokenProvider ,
5357 private IStore $ credentialStore ,
5458 private IEventDispatcher $ eventDispatcher ,
59+ private Session $ userSession ,
60+ private IUserManager $ userManager ,
61+ private IThrottler $ throttler ,
5562 ) {
5663 parent ::__construct ($ appName , $ request );
5764 }
@@ -165,4 +172,33 @@ public function rotateAppPassword(): DataResponse {
165172 'apppassword ' => $ newToken ,
166173 ]);
167174 }
175+
176+ /**
177+ * Confirm the user password
178+ *
179+ * @NoAdminRequired
180+ * @BruteForceProtection(action=sudo)
181+ *
182+ * @param string $password The password of the user
183+ *
184+ * @return DataResponse<Http::STATUS_OK, array{lastLogin: int}, array{}>|DataResponse<Http::STATUS_FORBIDDEN, array<empty>, array{}>
185+ *
186+ * 200: Password confirmation succeeded
187+ * 403: Password confirmation failed
188+ */
189+ #[UseSession]
190+ public function confirmUserPassword (string $ password ): DataResponse {
191+ $ loginName = $ this ->userSession ->getLoginName ();
192+ $ loginResult = $ this ->userManager ->checkPassword ($ loginName , $ password );
193+ if ($ loginResult === false ) {
194+ $ response = new DataResponse ([], Http::STATUS_FORBIDDEN );
195+ $ response ->throttle (['loginName ' => $ loginName ]);
196+ return $ response ;
197+ }
198+
199+ $ confirmTimestamp = time ();
200+ $ this ->session ->set ('last-password-confirm ' , $ confirmTimestamp );
201+ $ this ->throttler ->resetDelay ($ this ->request ->getRemoteAddress (), 'sudo ' , ['loginName ' => $ loginName ]);
202+ return new DataResponse (['lastLogin ' => $ confirmTimestamp ], Http::STATUS_OK );
203+ }
168204}
0 commit comments