├── .gitmodules ├── JsonHelper.php ├── LICENSE ├── OAuth2Client.alias.php ├── OAuth2Client.php ├── README.md ├── SpecialOAuth2Client.php ├── extension.json ├── i18n ├── en.json ├── nl.json └── qqq.json ├── modal.js └── tests └── phpunit └── JsonHelperTest.php /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendors/oauth2-client"] 2 | path = vendors/oauth2-client 3 | url = https://github.com/thephpleague/oauth2-client 4 | -------------------------------------------------------------------------------- /JsonHelper.php: -------------------------------------------------------------------------------- 1 | 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /OAuth2Client.alias.php: -------------------------------------------------------------------------------- 1 | array( 'OAuth2Client' ), 14 | ); 15 | 16 | /** Dutch (Nederlands) */ 17 | $specialPageAliases['nl'] = array( 18 | 'OAuth2Client' => array( 'OAuth2Client' ), 19 | ); 20 | -------------------------------------------------------------------------------- /OAuth2Client.php: -------------------------------------------------------------------------------- 1 | isLoggedIn() ) return true; 25 | 26 | 27 | # Due to bug 32276, if a user does not have read permissions, 28 | # $this->getTitle() will just give Special:Badtitle, which is 29 | # not especially useful as a returnto parameter. Use the title 30 | # from the request instead, if there was one. 31 | # see SkinTemplate->buildPersonalUrls() 32 | $page = Title::newFromURL( $wgRequest->getVal( 'title', '' ) ); 33 | 34 | $service_name = isset( $wgOAuth2Client['configuration']['service_name'] ) && 0 < strlen( $wgOAuth2Client['configuration']['service_name'] ) ? $wgOAuth2Client['configuration']['service_name'] : 'OAuth2'; 35 | if( isset( $wgOAuth2Client['configuration']['service_login_link_text'] ) && 0 < strlen( $wgOAuth2Client['configuration']['service_login_link_text'] ) ) { 36 | $service_login_link_text = $wgOAuth2Client['configuration']['service_login_link_text']; 37 | } else { 38 | $service_login_link_text = wfMessage('oauth2client-header-link-text', $service_name)->text(); 39 | } 40 | 41 | $inExt = ( null == $page || ('OAuth2Client' == substr( $page->getText(), 0, 12) ) || strstr($page->getText(), 'Logout') ); 42 | $personal_urls['anon_oauth_login'] = array( 43 | 'text' => $service_login_link_text, 44 | //'class' => , 45 | 'active' => false, 46 | ); 47 | if( $inExt ) { 48 | $personal_urls['anon_oauth_login']['href'] = Skin::makeSpecialUrlSubpage( 'OAuth2Client', 'redirect' ); 49 | } else { 50 | # Due to bug 32276, if a user does not have read permissions, 51 | # $this->getTitle() will just give Special:Badtitle, which is 52 | # not especially useful as a returnto parameter. Use the title 53 | # from the request instead, if there was one. 54 | # see SkinTemplate->buildPersonalUrls() 55 | $personal_urls['anon_oauth_login']['href'] = Skin::makeSpecialUrlSubpage( 56 | 'OAuth2Client', 57 | 'redirect', 58 | wfArrayToCGI( array( 'returnto' => $page ) ) 59 | ); 60 | } 61 | 62 | if( isset( $personal_urls['anonlogin'] ) ) { 63 | if( $inExt ) { 64 | $personal_urls['anonlogin']['href'] = Skin::makeSpecialUrl( 'Userlogin' ); 65 | } 66 | } 67 | return true; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MediaWiki OAuth2 Client 2 | MediaWiki implementation of the PHP League's [OAuth2 Client](https://github.com/thephpleague/oauth2-client), to allow MediaWiki to act as a client to any OAuth2 server. Currently maintained by [Schine GmbH](https://www.star-made.org/). 3 | 4 | Requires MediaWiki 1.25+. 5 | 6 | ## Installation 7 | 8 | Clone this repo into the extension directory. In the cloned directory, run 'git submodule update --init' to initialize the local configuration file and fetch all data from the OAuth2 client library. 9 | 10 | Finally, run [composer](https://getcomposer.org/) in /vendors/oauth2-client to install the library dependency. 11 | 12 | ``` 13 | composer install 14 | ``` 15 | 16 | ## Usage 17 | 18 | Add the following line to your LocalSettings.php file. 19 | 20 | ``` 21 | wfLoadExtension( 'MW-OAuth2Client' ); 22 | ``` 23 | 24 | Required settings to be added to LocalSettings.php 25 | 26 | ``` 27 | $wgOAuth2Client['client']['id'] = ''; // The client ID assigned to you by the provider 28 | $wgOAuth2Client['client']['secret'] = ''; // The client secret assigned to you by the provider 29 | 30 | $wgOAuth2Client['configuration']['authorize_endpoint'] = ''; // Authorization URL 31 | $wgOAuth2Client['configuration']['access_token_endpoint'] = ''; // Token URL 32 | $wgOAuth2Client['configuration']['api_endpoint'] = ''; // URL to fetch user JSON 33 | $wgOAuth2Client['configuration']['redirect_uri'] = ''; // URL for OAuth2 server to redirect to 34 | 35 | $wgOAuth2Client['configuration']['username'] = 'username'; // JSON path to username 36 | $wgOAuth2Client['configuration']['email'] = 'email'; // JSON path to email 37 | ``` 38 | 39 | The JSON path should be set to point to the appropriate attributes in the JSON. 40 | 41 | If the properties you want from your JSON object are nested, you can use periods. 42 | 43 | For example, if user JSON is 44 | 45 | ``` 46 | { 47 | "user": { 48 | "username": "my username", 49 | "email": "my email" 50 | } 51 | } 52 | ``` 53 | 54 | Then your JSON path configuration should be these 55 | 56 | ``` 57 | $wgOAuth2Client['configuration']['username'] = 'user.username'; // JSON path to username 58 | $wgOAuth2Client['configuration']['email'] = 'user.email'; // JSON path to email 59 | ``` 60 | 61 | You can see [Json Helper Test case](./tests/phpunit/JsonHelperTest.php) for more. 62 | 63 | The **Redirect URI** for your wiki should be: 64 | 65 | ``` 66 | http://your.wiki.domain/path/to/wiki/Special:OAuth2Client/callback 67 | ``` 68 | 69 | Optional further configuration 70 | 71 | ``` 72 | $wgOAuth2Client['configuration']['http_bearer_token'] = 'Bearer'; // Token to use in HTTP Authentication 73 | $wgOAuth2Client['configuration']['query_parameter_token'] = 'auth_token'; // query parameter to use 74 | $wgOAuth2Client['configuration']['scopes'] = 'read_citizen_info'; //Permissions 75 | 76 | $wgOAuth2Client['configuration']['service_name'] = 'Citizen Registry'; // the name of your service 77 | $wgOAuth2Client['configuration']['service_login_link_text'] = 'Login with StarMade'; // the text of the login link 78 | 79 | ``` 80 | 81 | Optional Authorization Callback 82 | 83 | Provide a callback and error message in the configuration that evaluates a conditional based upon the result of some business logic provided by the authorization endpoint response. 84 | 85 | ``` 86 | $wgOAuth2Client['configuration']['authz_callback'] = function($response) { 87 | if ($response['property']) { 88 | return true; 89 | } else { 90 | return false; 91 | } 92 | }; // return true or false based on something from the authorization response 93 | $wgOAuth2Client['configuration']['authz_failure_message'] // text of error message 94 | ``` 95 | 96 | 97 | 98 | ### Popup Window 99 | To use a popup window to login to the external OAuth2 server, copy the JS from modal.js to the [MediaWiki:Common.js](https://www.mediawiki.org/wiki/Manual:Interface/JavaScript) page on your wiki. 100 | 101 | ### Extension page 102 | https://www.mediawiki.org/wiki/Extension:OAuth2_Client 103 | 104 | ## License 105 | LGPL (GNU Lesser General Public License) http://www.gnu.org/licenses/lgpl.html 106 | -------------------------------------------------------------------------------- /SpecialOAuth2Client.php: -------------------------------------------------------------------------------- 1 | _provider = new \League\OAuth2\Client\Provider\GenericProvider([ 48 | 'clientId' => $wgOAuth2Client['client']['id'], // The client ID assigned to you by the provider 49 | 'clientSecret' => $wgOAuth2Client['client']['secret'], // The client password assigned to you by the provider 50 | 'redirectUri' => $wgOAuth2Client['configuration']['redirect_uri'], 51 | 'urlAuthorize' => $wgOAuth2Client['configuration']['authorize_endpoint'], 52 | 'urlAccessToken' => $wgOAuth2Client['configuration']['access_token_endpoint'], 53 | 'urlResourceOwnerDetails' => $wgOAuth2Client['configuration']['api_endpoint'], 54 | 'scopes' => $wgOAuth2Client['configuration']['scopes'] 55 | ]); 56 | } 57 | 58 | // default method being called by a specialpage 59 | public function execute( $parameter ){ 60 | $this->setHeaders(); 61 | switch($parameter){ 62 | case 'redirect': 63 | $this->_redirect(); 64 | break; 65 | case 'callback': 66 | $this->_handleCallback(); 67 | break; 68 | default: 69 | $this->_default(); 70 | break; 71 | } 72 | 73 | } 74 | 75 | private function _redirect() { 76 | 77 | global $wgRequest, $wgOut; 78 | $wgRequest->getSession()->persist(); 79 | $wgRequest->getSession()->set('returnto', $wgRequest->getVal( 'returnto' )); 80 | 81 | // Fetch the authorization URL from the provider; this returns the 82 | // urlAuthorize option and generates and applies any necessary parameters 83 | // (e.g. state). 84 | $authorizationUrl = $this->_provider->getAuthorizationUrl(); 85 | 86 | // Get the state generated for you and store it to the session. 87 | $wgRequest->getSession()->set('oauth2state', $this->_provider->getState()); 88 | $wgRequest->getSession()->save(); 89 | 90 | // Redirect the user to the authorization URL. 91 | $wgOut->redirect( $authorizationUrl ); 92 | } 93 | 94 | private function _handleCallback(){ 95 | global $wgRequest; 96 | 97 | try { 98 | $storedState = $wgRequest->getSession()->get('oauth2state'); 99 | // Enforce the `state` parameter to prevent clickjacking/CSRF 100 | if(isset($storedState) && $storedState != $_GET['state']) { 101 | if(isset($_GET['state'])) { 102 | throw new UnexpectedValueException("State parameter of callback does not match original state"); 103 | } else { 104 | throw new UnexpectedValueException("Required state parameter missing"); 105 | } 106 | } 107 | 108 | // Try to get an access token using the authorization code grant. 109 | $accessToken = $this->_provider->getAccessToken('authorization_code', [ 110 | 'code' => $_GET['code'] 111 | ]); 112 | } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) { 113 | exit($e->getMessage()); // Failed to get the access token or user details. 114 | } catch (UnexpectedValueException $e) { 115 | exit($e->getMessage()); 116 | } 117 | 118 | $resourceOwner = $this->_provider->getResourceOwner($accessToken); 119 | $user = $this->_userHandling( $resourceOwner->toArray() ); 120 | $user->setCookies(); 121 | 122 | global $wgOut, $wgRequest; 123 | $title = null; 124 | $wgRequest->getSession()->persist(); 125 | if( $wgRequest->getSession()->exists('returnto') ) { 126 | $title = Title::newFromText( $wgRequest->getSession()->get('returnto') ); 127 | $wgRequest->getSession()->remove('returnto'); 128 | $wgRequest->getSession()->save(); 129 | } 130 | 131 | if( !$title instanceof Title || 0 > $title->getArticleID() ) { 132 | $title = Title::newMainPage(); 133 | } 134 | $wgOut->redirect( $title->getFullURL() ); 135 | return true; 136 | } 137 | 138 | private function _default(){ 139 | global $wgOAuth2Client, $wgOut, $wgUser, $wgScriptPath, $wgExtensionAssetsPath; 140 | $service_name = ( isset( $wgOAuth2Client['configuration']['service_name'] ) && 0 < strlen( $wgOAuth2Client['configuration']['service_name'] ) ? $wgOAuth2Client['configuration']['service_name'] : 'OAuth2' ); 141 | 142 | $wgOut->setPagetitle( wfMessage( 'oauth2client-login-header', $service_name)->text() ); 143 | if ( !$wgUser->isLoggedIn() ) { 144 | $wgOut->addWikiMsg( 'oauth2client-you-can-login-to-this-wiki-with-oauth2', $service_name ); 145 | $wgOut->addWikiMsg( 'oauth2client-login-with-oauth2', $this->getTitle( 'redirect' )->getPrefixedURL(), $service_name ); 146 | 147 | } else { 148 | $wgOut->addWikiMsg( 'oauth2client-youre-already-loggedin' ); 149 | } 150 | return true; 151 | } 152 | 153 | /** 154 | * Optional callback settings in global $wgOAuth2Client 155 | * 156 | * Provide a callback and error message in the configuration that evaluates 157 | * a conditional based upon the result of some business logic provided by 158 | * the authorization endpoint response. 159 | * $wgOAuth2Client['configuration']['authz_callback'] 160 | * $wgOAuth2Client['configuration']['authz_failure_message'] 161 | */ 162 | protected function _userHandling( $response ) { 163 | global $wgOAuth2Client, $wgAuth, $wgRequest; 164 | 165 | if ( 166 | isset($wgOAuth2Client['configuration']['authz_callback']) 167 | && false === $wgOAuth2Client['configuration']['authz_callback']($response) 168 | ) { 169 | $callback_failure_message = isset($wgOAuth2Client['configuration']['authz_failure_message']) 170 | ? $wgOAuth2Client['configuration']['authz_failure_message'] 171 | : 'Not authorized'; 172 | throw new MWException($callback_failure_message); 173 | } 174 | 175 | $username = JsonHelper::extractValue($response, $wgOAuth2Client['configuration']['username']); 176 | $email = JsonHelper::extractValue($response, $wgOAuth2Client['configuration']['email']); 177 | Hooks::run("OAuth2ClientBeforeUserSave", [&$username, &$email, $response]); 178 | $user = User::newFromName($username, 'creatable'); 179 | if (!$user) { 180 | throw new MWException('Could not create user with username:' . $username); 181 | die(); 182 | } 183 | $user->setRealName($username); 184 | $user->setEmail($email); 185 | $user->load(); 186 | if ( !( $user instanceof User && $user->getId() ) ) { 187 | $user->addToDatabase(); 188 | // MediaWiki recommends below code instead of addToDatabase to create user but it seems to fail. 189 | // $authManager = MediaWiki\Auth\AuthManager::singleton(); 190 | // $authManager->autoCreateUser( $user, MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_SESSION ); 191 | $user->confirmEmail(); 192 | } 193 | $user->setToken(); 194 | 195 | // Setup the session 196 | $wgRequest->getSession()->persist(); 197 | $user->setCookies(); 198 | $this->getContext()->setUser( $user ); 199 | $user->saveSettings(); 200 | global $wgUser; 201 | $wgUser = $user; 202 | $sessionUser = User::newFromSession($this->getRequest()); 203 | $sessionUser->load(); 204 | return $user; 205 | } 206 | 207 | } 208 | -------------------------------------------------------------------------------- /extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MW-OAuth2Client", 3 | "version": "0.4", 4 | "author": [ 5 | "[http://dekeijzer.org Joost de Keijzer]", 6 | "[https://www.mediawiki.org/wiki/User:Nischayn22 Nischay Nahata]", 7 | "[https://star-made.org Schine GmbH]" 8 | ], 9 | "url": "https://www.mediawiki.org/wiki/Extension:OAuth2_Client", 10 | "descriptionmsg": "oauth2client-act-as-a-client-to-any-oauth2-server", 11 | "license-name": "LGPL-3.0", 12 | "type": "other", 13 | "AutoloadClasses": { 14 | "OAuth2ClientHooks": "OAuth2Client.php", 15 | "SpecialOAuth2Client": "SpecialOAuth2Client.php" 16 | }, 17 | "ExtensionMessagesFiles": { 18 | "OAuth2ClientAlias": "OAuth2Client.alias.php" 19 | }, 20 | "Hooks": { 21 | "PersonalUrls": [ 22 | "OAuth2ClientHooks::onPersonalUrls" 23 | ] 24 | }, 25 | "SpecialPages": { 26 | "OAuth2Client": "SpecialOAuth2Client" 27 | }, 28 | "MessagesDirs": { 29 | "MyExtension": [ 30 | "i18n" 31 | ] 32 | }, 33 | "manifest_version": 1 34 | } 35 | -------------------------------------------------------------------------------- /i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "oauth2client": "OAuth2 Client", 3 | "oauth2client-act-as-a-client-to-any-oauth2-server": "Act as a client to any OAuth2 server", 4 | "oauth2client-couldnotconnect": "Could not connect to OAuth2 Server", 5 | "oauth2client-header-link-text": "$1 login", 6 | "oauth2client-login-header": "$1 login", 7 | "oauth2client-you-can-login-to-this-wiki-with-oauth2": "You can login this wiki with your $1 account", 8 | "oauth2client-login-with-oauth2": "[[$1|Login with $2]]", 9 | "oauth2client-youre-already-loggedin": "You're already logged in.", 10 | "oauth2client-logout-header": "$1 logged out", 11 | "oauth2client-logged-out": "You have been logged out of this wiki.", 12 | "oauth2client-login-with-oauth2-again": "[[$1|You can login again with your $2 account]]" 13 | } 14 | -------------------------------------------------------------------------------- /i18n/nl.json: -------------------------------------------------------------------------------- 1 | { 2 | "oauth2client": "OAuth2 Client", 3 | 4 | "oauth2client-act-as-a-client-to-any-oauth2-server": "Act as a client to any OAuth2 server", 5 | "oauth2client-couldnotconnect": "Kon geen verbinding maken met de OAuth2 server", 6 | "oauth2client-header-link-text": "Aanmelden via $1", 7 | 8 | "oauth2client-login-header": "Aanmelden via $1", 9 | "oauth2client-you-can-login-to-this-wiki-with-oauth2": "U kunt zich aanmelden op deze wiki via uw $1 account", 10 | "oauth2client-login-with-oauth2": "[[$1|Aanmelden via $2]]", 11 | "oauth2client-youre-already-loggedin": "U bent al ingelogd.", 12 | 13 | "oauth2client-logout-header": "$1 uitgelogd", 14 | "oauth2client-logged-out": "U bent succesvol uitgelogd.", 15 | "oauth2client-login-with-oauth2-again": "[[$1|U kunt u weer aanmelden via uw $2 account]]" 16 | } -------------------------------------------------------------------------------- /i18n/qqq.json: -------------------------------------------------------------------------------- 1 | { 2 | "oauth2client": "Link of the special page", 3 | "oauth2client-login-header": "OAuth2 Login", 4 | "oauth2client-you-can-register-to-this-wiki-using-oauth2": "Explain to user that OAuth2 link is available", 5 | "oauth2client-login-with-oauth2": "link text", 6 | "oauth2client-youre-already-loggedin": "Message displayed on the default specialpage. tietoaccount replacement.", 7 | "oauth2client-act-as-a-client-to-any-oauth2-server": "Description of the extension, see setup file", 8 | "oauth2client-couldnotconnect": "Message for user when OAuth2 server is unavailable" 9 | } -------------------------------------------------------------------------------- /modal.js: -------------------------------------------------------------------------------- 1 | /* Any JavaScript here will be loaded for all users on every page load. */ 2 | $('li#pt-anon_oauth_login a').click(function(){ 3 | articlePath = mw.config.get('wgArticlePath'); 4 | url = articlePath.replace('$1', 'Special:OAuth2Client/redirect?returnto=Special:OAuth2Client/close'); 5 | var left = (screen.width/2) - 200; 6 | var above = (screen.height/2) - 200; 7 | newwindow = window.open(url, "_blank", "resizable=yes, scrollbars=yes, titlebar=yes, width=400, height=400, top="+above+", left="+left); 8 | return false; 9 | }) 10 | 11 | if (mw.config.get('wgTitle') == 'OAuth2Client/close') { 12 | window.opener.location.reload(); 13 | window.close(); 14 | } 15 | -------------------------------------------------------------------------------- /tests/phpunit/JsonHelperTest.php: -------------------------------------------------------------------------------- 1 | array( 16 | "username" => "username", 17 | "email" => "localhost@email.com" 18 | ) 19 | ); 20 | self::assertEquals("localhost@email.com", JsonHelper::extractValue($json_array, "user.email")); 21 | self::assertEquals("username", JsonHelper::extractValue($json_array, "user.username")); 22 | self::assertEquals("username", JsonHelper::extractValue($json_array, "user")["username"]); 23 | self::assertNull(JsonHelper::extractValue($json_array, "user.emails")); 24 | self::assertNull(JsonHelper::extractValue($json_array, "$.user.email")); 25 | } 26 | 27 | protected function tearDown() 28 | { 29 | parent::tearDown(); 30 | } 31 | } 32 | --------------------------------------------------------------------------------