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 0000000..e442571 Binary files /dev/null and b/secrets/mediakiwi/mediawiki-oauth.age differ diff --git a/secrets/mediakiwi/mediawiki-openid.age b/secrets/mediakiwi/mediawiki-openid.age deleted file mode 100644 index ceae6cf..0000000 Binary files a/secrets/mediakiwi/mediawiki-openid.age and /dev/null differ