Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 41 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
TOTPSecondaryAuthenticationProvider | |
0.00% |
0 / 41 |
|
0.00% |
0 / 4 |
90 | |
0.00% |
0 / 1 |
getAuthenticationRequests | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
beginSecondaryAuthentication | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
continueSecondaryAuthentication | |
0.00% |
0 / 31 |
|
0.00% |
0 / 1 |
30 | |||
beginSecondaryAccountCreation | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
16 | * http://www.gnu.org/copyleft/gpl.html |
17 | */ |
18 | |
19 | namespace MediaWiki\Extension\OATHAuth\Auth; |
20 | |
21 | use MediaWiki\Auth\AbstractSecondaryAuthenticationProvider; |
22 | use MediaWiki\Auth\AuthenticationRequest; |
23 | use MediaWiki\Auth\AuthenticationResponse; |
24 | use MediaWiki\Auth\AuthManager; |
25 | use MediaWiki\Extension\OATHAuth\Module\TOTP; |
26 | use MediaWiki\MediaWikiServices; |
27 | use MediaWiki\User\User; |
28 | use Message; |
29 | |
30 | /** |
31 | * AuthManager secondary authentication provider for TOTP second-factor authentication. |
32 | * |
33 | * After a successful primary authentication, requests a time-based one-time password |
34 | * (typically generated by a mobile app such as Google Authenticator) from the user. |
35 | * |
36 | * @see AuthManager |
37 | * @see https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm |
38 | */ |
39 | class TOTPSecondaryAuthenticationProvider extends AbstractSecondaryAuthenticationProvider { |
40 | |
41 | /** |
42 | * @param string $action |
43 | * @param array $options |
44 | * |
45 | * @return array |
46 | */ |
47 | public function getAuthenticationRequests( $action, array $options ) { |
48 | // don't ask for anything initially, so the second factor is on a separate screen |
49 | return []; |
50 | } |
51 | |
52 | /** |
53 | * If the user has enabled two-factor authentication, request a second factor. |
54 | * |
55 | * @param User $user |
56 | * @param array $reqs |
57 | * |
58 | * @return AuthenticationResponse |
59 | */ |
60 | public function beginSecondaryAuthentication( $user, array $reqs ) { |
61 | $userRepo = MediaWikiServices::getInstance()->getService( 'OATHUserRepository' ); |
62 | $authUser = $userRepo->findByUser( $user ); |
63 | |
64 | if ( !( $authUser->getModule() instanceof TOTP ) ) { |
65 | return AuthenticationResponse::newAbstain(); |
66 | } |
67 | |
68 | return AuthenticationResponse::newUI( |
69 | [ new TOTPAuthenticationRequest() ], |
70 | wfMessage( 'oathauth-auth-ui' ), |
71 | ); |
72 | } |
73 | |
74 | /** |
75 | * Verify the second factor. |
76 | * @inheritDoc |
77 | */ |
78 | public function continueSecondaryAuthentication( $user, array $reqs ) { |
79 | /** @var TOTPAuthenticationRequest $request */ |
80 | $request = AuthenticationRequest::getRequestByClass( $reqs, TOTPAuthenticationRequest::class ); |
81 | if ( !$request ) { |
82 | return AuthenticationResponse::newUI( [ new TOTPAuthenticationRequest() ], |
83 | wfMessage( 'oathauth-login-failed' ), 'error' ); |
84 | } |
85 | |
86 | $userRepo = MediaWikiServices::getInstance()->getService( 'OATHUserRepository' ); |
87 | $authUser = $userRepo->findByUser( $user ); |
88 | $token = $request->OATHToken; |
89 | |
90 | if ( !( $authUser->getModule() instanceof TOTP ) ) { |
91 | $this->logger->warning( 'Two-factor authentication was disabled mid-authentication for {user}', [ |
92 | 'user' => $user->getName(), |
93 | ] ); |
94 | return AuthenticationResponse::newAbstain(); |
95 | } |
96 | |
97 | // Don't increase pingLimiter, just check for limit exceeded. |
98 | if ( $user->pingLimiter( 'badoath', 0 ) ) { |
99 | return AuthenticationResponse::newUI( |
100 | [ new TOTPAuthenticationRequest() ], |
101 | new Message( |
102 | 'oathauth-throttled', |
103 | // Arbitrary duration given here |
104 | [ Message::durationParam( 60 ) ] |
105 | ), 'error' ); |
106 | } |
107 | |
108 | if ( $authUser->getModule()->verify( $authUser, [ 'token' => $token ] ) ) { |
109 | return AuthenticationResponse::newPass(); |
110 | } |
111 | |
112 | // Increase rate limit counter for failed request |
113 | $user->pingLimiter( 'badoath' ); |
114 | |
115 | $this->logger->info( 'OATHAuth user {user} failed OTP token/recovery code from {clientip}', [ |
116 | 'user' => $user->getName(), |
117 | 'clientip' => $user->getRequest()->getIP(), |
118 | ] ); |
119 | |
120 | return AuthenticationResponse::newUI( |
121 | [ new TOTPAuthenticationRequest() ], |
122 | wfMessage( 'oathauth-login-failed' ), |
123 | 'error' |
124 | ); |
125 | } |
126 | |
127 | /** |
128 | * @param User $user |
129 | * @param User $creator |
130 | * @param array $reqs |
131 | * |
132 | * @return AuthenticationResponse |
133 | */ |
134 | public function beginSecondaryAccountCreation( $user, $creator, array $reqs ) { |
135 | return AuthenticationResponse::newAbstain(); |
136 | } |
137 | } |