1<?php 2 3namespace dokuwiki\plugin\oauthkeycloak; 4 5use dokuwiki\plugin\oauth\Service\AbstractOAuth2Base; 6use OAuth\Common\Http\Uri\Uri; 7 8/** 9 * Custom Service for Keycloak oAuth 10 */ 11class Keycloak extends AbstractOAuth2Base 12{ 13 /** 14 * Defined scopes are listed here: 15 * @link https://www.keycloak.org/docs/latest/server_admin/#_client_scopes 16 */ 17 const SCOPE_OPENID = 'openid'; 18 19 /** 20 * Endpoints are listed here: 21 * @link https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#authorization-server-metadata 22 */ 23 const ENDPOINT_AUTH = 'authorization_endpoint'; 24 const ENDPOINT_TOKEN = 'token_endpoint'; 25 const ENDPOINT_USERINFO = 'userinfo_endpoint'; 26 /** 27 * This endpoint is used for backchannel logout and documented here 28 * @link https://www.keycloak.org/docs/latest/server_admin/#con-basic-settings_server_administration_guide 29 */ 30 const ENDPOINT_LOGOUT = 'end_session_endpoint'; 31 32 protected $discovery; 33 34 /** 35 * Return URI of discovered endpoint 36 * 37 * @return string 38 */ 39 public function getEndpoint(string $endpoint) 40 { 41 if (!isset($this->discovery)) { 42 $plugin = plugin_load('helper', 'oauthkeycloak'); 43 $json = file_get_contents($plugin->getConf('openidurl')); 44 if (!$json) throw new \Exception('Failed accessing ' . $plugin->getConf('openidurl')); 45 $this->discovery = json_decode($json, true); 46 } 47 if (!isset($this->discovery[$endpoint])) return ''; 48 return $this->discovery[$endpoint]; 49 } 50 51 /** @inheritdoc */ 52 public function getAuthorizationEndpoint() 53 { 54 return new Uri($this->getEndpoint(self::ENDPOINT_AUTH)); 55 } 56 57 /** @inheritdoc */ 58 public function getAccessTokenEndpoint() 59 { 60 return new Uri($this->getEndpoint(self::ENDPOINT_TOKEN)); 61 } 62 63 /** @inheritdoc */ 64 protected function getAuthorizationMethod() 65 { 66 return static::AUTHORIZATION_METHOD_HEADER_BEARER; 67 } 68 69 /** 70 * Logout from Keycloak 71 * 72 * @return void 73 * @throws \OAuth\Common\Exception\Exception 74 */ 75 public function logout() 76 { 77 $token = $this->getStorage()->retrieveAccessToken($this->service()); 78 $refreshToken = $token->getRefreshToken(); 79 80 if (!$refreshToken) { 81 return; 82 } 83 84 $parameters = [ 85 'client_id' => $this->credentials->getConsumerId(), 86 'client_secret' => $this->credentials->getConsumerSecret(), 87 'refresh_token' => $refreshToken, 88 ]; 89 90 $this->httpClient->retrieveResponse( 91 new Uri($this->getEndpoint(self::ENDPOINT_LOGOUT)), 92 $parameters, 93 $this->getExtraOAuthHeaders() 94 ); 95 } 96} 97