MediaWiki REL1_33
SpecialOATHEnable.php
Go to the documentation of this file.
1<?php
27
29 private $OATHUser;
30
37 public function __construct( OATHUserRepository $repository, OATHUser $user ) {
38 parent::__construct( 'OATH', 'oathauth-enable', false );
39
40 $this->OATHRepository = $repository;
41 $this->OATHUser = $user;
42 }
43
44 public function doesWrites() {
45 return true;
46 }
47
53 public function alterForm( HTMLForm $form ) {
54 $form->setMessagePrefix( 'oathauth' );
55 $form->setWrapperLegend( false );
56 $form->getOutput()->setPageTitle( $this->msg( 'oathauth-enable' ) );
57 $form->getOutput()->addModules( 'ext.oath.showqrcode' );
58 $form->getOutput()->addModuleStyles( 'ext.oath.showqrcode.styles' );
59 }
60
64 protected function getDisplayFormat() {
65 return 'ooui';
66 }
67
71 public function requiresUnblock() {
72 return false;
73 }
74
82 protected function checkExecutePermissions( User $user ) {
83 parent::checkExecutePermissions( $user );
84
85 $this->requireLogin();
86 }
87
91 public function execute( $par ) {
92 $this->getOutput()->disallowUserJs();
93 parent::execute( $par );
94 }
95
99 protected function getFormFields() {
100 $key = $this->getRequest()->getSessionData( 'oathauth_key' );
101
102 if ( $key === null ) {
104 $this->getRequest()->setSessionData( 'oathauth_key', $key );
105 }
106
107 $secret = $key->getSecret();
108 $label = "{$this->OATHUser->getIssuer()}:{$this->OATHUser->getAccount()}";
109 $qrcodeUrl = "otpauth://totp/"
110 . rawurlencode( $label )
111 . "?secret="
112 . rawurlencode( $secret )
113 . "&issuer="
114 . rawurlencode( $this->OATHUser->getIssuer() );
115
116 $qrcodeElement = Html::element( 'div', [
117 'data-mw-qrcode-url' => $qrcodeUrl,
118 'class' => 'mw-display-qrcode',
119 // Include width/height, so js won't re-arrange layout
120 // And non-js users will have this hidden with CSS
121 'style' => 'width: 256px; height: 256px;'
122 ] );
123
124 return [
125 'app' => [
126 'type' => 'info',
127 'default' => $this->msg( 'oathauth-step1-test' )->escaped(),
128 'raw' => true,
129 'section' => 'step1',
130 ],
131 'qrcode' => [
132 'type' => 'info',
133 'default' => $qrcodeElement,
134 'raw' => true,
135 'section' => 'step2',
136 ],
137 'manual' => [
138 'type' => 'info',
139 'label-message' => 'oathauth-step2alt',
140 'default' =>
141 '<strong>' . $this->msg( 'oathauth-account' )->escaped() . '</strong><br/>'
142 . $this->OATHUser->getAccount() . '<br/><br/>'
143 . '<strong>' . $this->msg( 'oathauth-secret' )->escaped() . '</strong><br/>'
144 . '<kbd>' . $this->getSecretForDisplay( $key ) . '</kbd><br/>',
145 'raw' => true,
146 'section' => 'step2',
147 ],
148 'scratchtokens' => [
149 'type' => 'info',
150 'default' =>
151 $this->msg( 'oathauth-scratchtokens' )
152 . $this->createResourceList( $this->getScratchTokensForDisplay( $key ) ),
153 'raw' => true,
154 'section' => 'step3',
155 ],
156 'token' => [
157 'type' => 'text',
158 'default' => '',
159 'label-message' => 'oathauth-entertoken',
160 'name' => 'token',
161 'section' => 'step4',
162 ],
163 'returnto' => [
164 'type' => 'hidden',
165 'default' => $this->getRequest()->getVal( 'returnto' ),
166 'name' => 'returnto',
167 ],
168 'returntoquery' => [
169 'type' => 'hidden',
170 'default' => $this->getRequest()->getVal( 'returntoquery' ),
171 'name' => 'returntoquery',
172 ]
173 ];
174 }
175
181 public function onSubmit( array $formData ) {
183 $key = $this->getRequest()->getSessionData( 'oathauth_key' );
184
185 if ( $key->isScratchToken( $formData['token'] ) ) {
186 // A scratch token is not allowed for enrollement
187 \MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )->info(
188 'OATHAuth {user} attempted to enable 2FA using a scratch token from {clientip}', [
189 'user' => $this->getUser()->getName(),
190 'clientip' => $this->getRequest()->getIP(),
191 ]
192 );
193 return [ 'oathauth-noscratchforvalidation' ];
194 }
195 if ( !$key->verifyToken( $formData['token'], $this->OATHUser ) ) {
196 \MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )->info(
197 'OATHAuth {user} failed to provide a correct token while enabling 2FA from {clientip}', [
198 'user' => $this->getUser()->getName(),
199 'clientip' => $this->getRequest()->getIP(),
200 ]
201 );
202 return [ 'oathauth-failedtovalidateoath' ];
203 }
204
205 $this->getRequest()->setSessionData( 'oathauth_key', null );
206 $this->OATHUser->setKey( $key );
207 $this->OATHRepository->persist( $this->OATHUser, $this->getRequest()->getIP() );
208
209 return true;
210 }
211
212 public function onSuccess() {
213 $this->getOutput()->addWikiMsg( 'oathauth-validatedoath' );
214 $this->getOutput()->returnToMain();
215 }
216
221 private function createResourceList( $resources ) {
222 $resourceList = '';
223 foreach ( $resources as $resource ) {
224 $resourceList .= Html::rawElement( 'li', [], Html::rawElement( 'kbd', [], $resource ) );
225 }
226 return Html::rawElement( 'ul', [], $resourceList );
227 }
228
237 protected function getSecretForDisplay( OATHAuthKey $key ) {
238 return $this->tokenFormatterFunction( $key->getSecret() );
239 }
240
249 protected function getScratchTokensForDisplay( OATHAuthKey $key ) {
250 return array_map( [ $this, 'tokenFormatterFunction' ], $key->getScratchTokens() );
251 }
252
259 private function tokenFormatterFunction( $token ) {
260 return implode( ' ', str_split( $token, 4 ) );
261 }
262}
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two and(2) offer you this license which gives you legal permission to copy
Special page which uses an HTMLForm to handle processing.
string null $par
The sub-page of the special page.
Object handling generic submission, CSRF protection, layout and other logic for UI forms.
Definition HTMLForm.php:133
Class representing a two-factor key.
static newFromRandom()
Make a new key from random values.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
Definition OATHUser.php:24
getAccount()
Definition OATHUser.php:62
getIssuer()
Definition OATHUser.php:51
setKey(OATHAuthKey $key=null)
Set the key associated with this user.
Definition OATHUser.php:80
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
checkExecutePermissions(User $user)
Require users to be logged in.
onSubmit(array $formData)
onSuccess()
Do something exciting on successful processing of the form, most likely to show a confirmation messag...
getSecretForDisplay(OATHAuthKey $key)
Retrieve the current secret for display purposes.
__construct(OATHUserRepository $repository, OATHUser $user)
Initialize the OATH user based on the current local User object in the context.
tokenFormatterFunction( $token)
Formats a key or scratch token by creating groups of 4 separated by space characters.
createResourceList( $resources)
OATHUserRepository $OATHRepository
alterForm(HTMLForm $form)
Set the page title and add JavaScript RL modules.
doesWrites()
Indicates whether this special page may perform database writes.
getScratchTokensForDisplay(OATHAuthKey $key)
Retrieve current scratch tokens for display purposes.
getName()
Get the name of this Special Page.
getOutput()
Get the OutputPage being used for this instance.
requireLogin( $reasonMsg='exception-nologin-text', $titleMsg='exception-nologin')
If the user is not logged in, throws UserNotLoggedIn error.
getUser()
Shortcut to get the User executing this instance.
msg( $key)
Wrapper around wfMessage that sets the current context.
getRequest()
Get the WebRequest being used for this instance.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition User.php:48
return true to allow those checks to and false if checking is done & $user
Definition hooks.txt:1510
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))