From 55767e5690bd78246bf5281d1f369ff67be9085c Mon Sep 17 00:00:00 2001 From: Pyjacpp Date: Mon, 23 Mar 2026 22:20:33 +0100 Subject: [PATCH] =?UTF-8?q?feat:=E2=80=AFOAuth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hosts/vm/mediakiwi/WSONoteKfetAuth/README | 14 ++ .../mediakiwi/WSONoteKfetAuth/extension.json | 25 ++++ .../WSONoteKfetAuth/src/NoteKfetAuth.php | 137 ++++++++++++++++++ hosts/vm/mediakiwi/mediawiki.nix | 16 +- secrets/mediakiwi/mediawiki-oauth.age | Bin 0 -> 2000 bytes secrets/mediakiwi/mediawiki-openid.age | Bin 2028 -> 0 bytes 6 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 hosts/vm/mediakiwi/WSONoteKfetAuth/README create mode 100644 hosts/vm/mediakiwi/WSONoteKfetAuth/extension.json create mode 100644 hosts/vm/mediakiwi/WSONoteKfetAuth/src/NoteKfetAuth.php create mode 100644 secrets/mediakiwi/mediawiki-oauth.age delete mode 100644 secrets/mediakiwi/mediawiki-openid.age diff --git a/hosts/vm/mediakiwi/WSONoteKfetAuth/README b/hosts/vm/mediakiwi/WSONoteKfetAuth/README new file mode 100644 index 0000000..0d3eae9 --- /dev/null +++ b/hosts/vm/mediakiwi/WSONoteKfetAuth/README @@ -0,0 +1,14 @@ +# NoteKfetAuth + +Extension pour médiawiki pour ajouter le support de l'autentification par Note +via l'extension WSOAuth. + +## Installation + +Il faut enregistrer l'extension comme provider + +``` +$wgOAuthCustomAuthProviders = [ + 'note' => WSOAuthNoteKfetAuth\NoteKfetAuth::class +]; +``` diff --git a/hosts/vm/mediakiwi/WSONoteKfetAuth/extension.json b/hosts/vm/mediakiwi/WSONoteKfetAuth/extension.json new file mode 100644 index 0000000..efbb583 --- /dev/null +++ b/hosts/vm/mediakiwi/WSONoteKfetAuth/extension.json @@ -0,0 +1,25 @@ +{ + "name": "WSONoteKfetAuth", + "author": [ + "Pyjacpp" + ], + "url": "https://gitlab.crans.org/nounou/WSONoteKfet", + "description": "Implementation of the NoteKfet OAuth2 for the WSOAuth extension", + "type": "other", + "requires": { + "MediaWiki": ">= 1.35.0", + "extensions": { + "WSOAuth": ">= 9.0" + } + }, + "AutoloadNamespaces": { + "WSONoteKfetAuth\\": "src/" + }, + "config": { + "NoteKfetUrl": { + "description": "The url of the NoteKfet.", + "value": "https://note.crans.org/" + } + }, + "manifest_version": 2 +} \ No newline at end of file diff --git a/hosts/vm/mediakiwi/WSONoteKfetAuth/src/NoteKfetAuth.php b/hosts/vm/mediakiwi/WSONoteKfetAuth/src/NoteKfetAuth.php new file mode 100644 index 0000000..464213c --- /dev/null +++ b/hosts/vm/mediakiwi/WSONoteKfetAuth/src/NoteKfetAuth.php @@ -0,0 +1,137 @@ +clientId = $clientId; + $this->clientSecret = $clientSecret; + } + + /** + * @inheritDoc + */ + public function login( ?string &$key, ?string &$secret, ?string &$authUrl ): bool { + + $state = random_int(PHP_INT_MIN, PHP_INT_MAX); + $secret = "$state"; + $authUrl = $GLOBALS['wgNoteKfetUrl'] . "o/authorize/?" . http_build_query( + 'client_id' => $this->clientId, + 'response_type' => 'code', + 'scope' => '1_1', + 'state' => $secret, + ); + + return true; + } + + /** + * @inheritDoc + */ + public function logout( UserIdentity &$user ): void { + } + + /** + * @inheritDoc + */ + public function getUser( string $key, string $secret, &$errorMessage ) { + if ( !isset( $_GET['code'] ) ) { + return false; + } + + if ( !isset( $_GET['state'] ) || empty( $_GET['state'] ) || ( $_GET['state'] !== $secret ) ) { + return false; + } + + try { + $token = $this->getAccessTokens( $_GET['code'] ); + $userInfos = $this->getUserInfos( $token ); + + return [ + 'name' => $userInfos->normalized_name, + 'realname' => $userInfos->username, + 'email' => $userInfos->email, + ]; + } catch ( \Exception $e ) { + return false; + } + } + + private function getAccessTokens( string $code ) { + $data = [ + 'grant_type' => 'authorization_code', + 'client_id' => $this->clientId, + 'client_secret' => $this->clientSecret, + 'code' => $code, + ]; + + $options = [ + 'http' => [ + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', + 'content' => http_build_query($data), + ], + ]; + + $context = stream_context_create($options); + $response = file_get_contents($GLOBALS['wgNoteKfetUrl'] . 'o/oauth/token/', false, $context); + $tokens = json_decode($response); + return $tokens->access_token; + } + + private function getUserInfos( string $token ) { + $options = [ + 'http' => [ + 'method' => 'GET', + 'header' => "Authorization: Bearer $token", + ], + ]; + + $context = stream_context_create($options); + $response = file_get_contents($GLOBALS['wgNoteKfetUrl'] . 'api/me/', false, $context); + return json_decode($response); + } + + /** + * @inheritDoc + */ + public function saveExtraAttributes( int $id ): void { + } +} diff --git a/hosts/vm/mediakiwi/mediawiki.nix b/hosts/vm/mediakiwi/mediawiki.nix index c0217f0..15cd91b 100644 --- a/hosts/vm/mediakiwi/mediawiki.nix +++ b/hosts/vm/mediakiwi/mediawiki.nix @@ -106,6 +106,9 @@ in $wgPluggableAuth_EnableLocalLogin = true; $LDAPAuthentication2AllowLocalLogin = true; $LDAPProviderDomainConfigs = "${config.age.secrets.mediawiki-ldap.path}"; + $wgOAuthCustomAuthProviders = [ + 'note' => WSOAuthNoteKfetAuth\NoteKfetAuth::class + ]; $wgPluggableAuth_Config = [ "Compte Crans" => [ 'plugin' => 'LDAPAuthentication2', @@ -114,8 +117,8 @@ in ] ], "Note BDE" => [ - 'plugin' => 'OpenIDConnect', - 'data' => require('${config.age.secrets.mediawiki-openid.path}'), + 'plugin' => 'WSOAuth', + 'data' => require('${config.age.secrets.mediawiki-oauth.path}'), ] ]; @@ -257,15 +260,16 @@ in # Pas de meilleure solution à ma connaissance pour suivre les releases. sha256 = "sha256-oi5rliHb4KnLbvQxO7MGuLp/FEucoGR/Z0NP1gmbgMc="; }; - OpenIDConnect = pkgs.fetchFromGitHub { - name = "OpenIDConnect"; + WSOAuth = pkgs.fetchFromGitHub { + name = "WSOAuth"; owner = "wikimedia"; - repo = "mediawiki-extensions-OpenIDConnect"; + repo = "mediawiki-extensions-WSOAuth"; rev = "REL" + major + "_" + minor; # Le SHA doit être changé à chaque nouveau commit de traduction. # Pas de meilleure solution à ma connaissance pour suivre les releases. - sha256 = "sha256-KoBULn53xnY+ydodeTGN7YEoqgLr9qhhuR5mNibbh5s="; + sha256 = "sha256-1jv4nmkxky1dx7833sacsbqww54yb9glrnl1360b13h2z5fhwdxp"; }; + WSONoteKfetAuth = ./WSONoteKfetAuth; }; }; } diff --git a/secrets/mediakiwi/mediawiki-oauth.age b/secrets/mediakiwi/mediawiki-oauth.age new file mode 100644 index 0000000000000000000000000000000000000000..e442571d799062c48266bba318cd37f6914617ec GIT binary patch literal 2000 zcmZXU>&xT@8O2vc#e5Q>t6LGqij+3{nn@AVn~|XyFtOiHBM{iFbt9JK%OTT zU@g0x5GPIsaTdY0gb&w!Y3?a4P>58Ls&Qmd8ss>WE(9)gsYuMC?SmA%H*_V+hEn6j zqy15e-kj7Fze72`(b5~ULD-lKX9c~?hK=H(4Jl`V7%SAcxz6 z_zrWjZr=uTp)wQ3NCyin@OVh&mhl9s)@URt3dQMeLAxQa!{}wr*J3sc5VcU-vC zr6Th^*=?-UhPxY~X!R$uwoFAnrFC7HR$Qf&@fwwME*oDou+C&a6nOsscwP z=)&sNsb=qOA~gd?!gonV>nm8SR2i7&DaA$J}I) zgQaQ(f+nRS#>5k`Z8^^Ll@X(}Rzqbt!A&I^l7Vcmx@BGyEY8dkT$8qtUrnZUtQtK? zFKpgai8Wg7xOA>*wb_hkZj?s2I~~nHrdU^9K*M{wY5AT>+a;j|V3^nvx`Et?PU~o~ zt}_IwbHok#LFuj5EV)InJ~1DymR-SVLxcxFa=IfYBC837F7MWcja5yQYc$5s`f(X( zOkl<&%vh_ctxFd}^Twz5jM>NWzFe{c5jgsYQz(=@zq5)NzQ*i%%Xb-m@pvS#|5T~IC^j+SOzm!u##>gx5x?`uxGfxAc5 zm|37O`wlEGF})p?lL_C_1lk+Vl@PR}CDE2B-c%?Q3OET4bWHI9XO&0^Q91cM0#h4< z90N*lg{Oo?FC3*5$Bh;o7|o1z_G+R3d#b#JK$c`@fNr?~)ko%Wo#?(2uC{RmtID4B z_+>y>iYF7!e&ek-6BCef#4Fh-n~pTnaU?s^l5)e%N611E2Ky=mJvYpMl1kw#7b-2(+)F3>pbu?M&h@{)-MyR$tB#+&r*(Sa*@W>8_ z2NbU!PUwoQL!R%orMAhthl2_n92|5sQ8SVSxpdIXz^C@oY(TWxWl~PsYfN)$%i>B>fdhEZ z1x}s$MCXsqg`d9nvL&l`UBB+U@u5q_=N>)v*|)#*Df#cRcdMlaFB1Q}6G+e9^{jb? zg#Z2e^~au-;`{!9{Qh3OJU@T%lMmeS81gcF{Mg0&&+e+fep{K`{Jk3S@y}7AG-U( zS1+CU&<)JR;NtH-IN$!N^U@1%J$>y>Kfd~n^3t8ur{a%(=JXTJ1IJ#x|D_90U%Txl z?RfaSc%X4;|LbZM;!VG2N>gq0Bn966j2!Dv*(> zAVCiJpk7j4JQ&6UcrrDFtU}g;nE{Dfvb{7#1&57VL9-BevjlZh>MHG86=j z>TDW$ySM0wgr<6pzy@VB*g#o9I5uOW3u|I(PD}PEPzd#MYt6HAyHUY9tbj?C3zDp{ zaL%xEImd#CUplSUtad8I)2U&w96=bQ=lCGJp{+Bkq0rW}M*tHgPqk_-##4slI;3I_ zLCLmti8TAJ96)h=p8`9A@?b%VHcEFDp1?4Rbi3xYR%< zJ572R^~R_)4Kgi_P|3%8u!sx|hw&Ipo);@*ofsjKnl^wh%mvx03vsd0TXfq_n{wZB zRRP~xtG+Y0qXe?Cc)`yk5svh3Im9Y+Jg*dGgj(~09|J_Vc<$vU>Efuv6-*Ms_MkVm8w=L|Z}0YTDf2PT%pnyA5KEJ1#@rHHmU z)^dDUNokKieiN+nbiFqT1wB=Ecmkc>?>)xod z5QA*xU|6y#-N<2;bsG!XD8y$9ncMA90T%>;a9aTJjJlLfS>qLDWmtt>fF%u*q)3|v z7i*oFvZf5}>Z~@b+iQiim|CO$+C^nX5*2$$Xilmo%ViQwOuO2x zA-aq&Y)I`Y9*R)vV||6v>W$M=TczVnHF z$K>ti%&RXQd+Qfxp`Q%i`}td*_~xZQF2+`P=Dv4?=*rQf`%b;|o0E^4uN?YHcINAQ z_nq4_ATID1FYI~tz?LZ8z@ I5C2vCFT;e)fB*mh