generate_unique_sequence(32, true); $tikilib->set_preference('oauthserver_encryption_key', $encryptionKey); } return $prefs['oauthserver_encryption_key']; } public function getPublicKey() { global $prefs; $tikilib = TikiLib::lib('tiki'); if (empty($prefs['oauthserver_public_key'])) { $keys = $this->generateKeys(); $tikilib->set_preference('oauthserver_public_key', $keys['public']); $tikilib->set_preference('oauthserver_private_key', $keys['private']); } return $prefs['oauthserver_public_key']; } public function getPrivateKey() { global $prefs; $tikilib = TikiLib::lib('tiki'); if (empty($prefs['oauthserver_private_key'])) { $keys = $this->generateKeys(); $tikilib->set_preference('oauthserver_public_key', $keys['public']); $tikilib->set_preference('oauthserver_private_key', $keys['private']); } return $prefs['oauthserver_private_key']; } public function getClientRepository() { $database = TikiLib::lib('db'); return new ClientRepository($database); } public function getAccessTokenRepository() { return new AccessTokenRepository(); } public function getServer() { if (empty($this->server)) { $this->server = new AuthorizationServer( $this->getClientRepository(), $this->getAccessTokenRepository(), new ScopeRepository(), $this->getPrivateKey(), $this->getEncryptionKey() ); } return $this->server; } public function getUserEntity() { global $user; $entity = new UserEntity(); $entity->setIdentifier($user); return $entity; } public function determineServerGrant() { global $user; $server = $this->getServer(); if (! empty($user)) { // TODO: this is legacy, see if xmpp/converse really need it $grant = new ImplicitGrant(new \DateInterval('PT1H'), '?'); $server->enableGrantType($grant); } // end user/app auth flow $grant = new AuthCodeGrant( new AuthCodeRepository(), new RefreshTokenRepository(), new \DateInterval('PT10M') ); $grant->setRefreshTokenTTL(new \DateInterval('P1M')); $server->enableGrantType($grant); // end user/app refresh token flow $grant = new RefreshTokenGrant(new RefreshTokenRepository()); $grant->setRefreshTokenTTL(new \DateInterval('P1M')); $server->enableGrantType( $grant, new \DateInterval('PT1H') ); // server-to-server client credentials flow $server->enableGrantType( new ClientCredentialsGrant(), new \DateInterval('PT1H') ); return $this; } public function getClient($client_id) { return $this->getClientRepository()->get($client_id); } public function createClient($data) { $repo = $this->getClientRepository(); if (empty($data['client_id'])) { $data['client_id'] = $repo::generateSecret(32); } if (empty($data['client_secret'])) { $data['client_secret'] = $repo::generateSecret(64); } $entity = ClientRepository::build($data); return $repo->create($entity); } public function checkAuthToken($request) { $util = new Services_OAuthServer_Utilities(); $request = $util->tiki2Psr7Request($request); $server = new ResourceServer( $this->getAccessTokenRepository(), new TikiCryptKey($this->getPublicKey()) ); try { $request = $server->validateAuthenticatedRequest($request); return $request->getAttribute('oauth_access_token_id'); } catch (OAuthServerException $e) { TikiLib::lib('access')->display_error(null, $e->getMessage() . ' ' . $e->getHint(), 403); } } private function generateKeys() { $error_message = tr('OAuth server is not configured correctly: missing public/private key pair and autogeneration failed.'); if (! function_exists('openssl_pkey_new')) { throw new Exception($error_message); } $private_key = openssl_pkey_new([ 'private_key_type' => OPENSSL_KEYTYPE_RSA, 'private_key_bits' => 2048, ]); if (! $private_key) { throw new Exception($error_message); } $details = openssl_pkey_get_details($private_key); if (! $details) { throw new Exception($error_message); } $public_key_pem = $details['key'] ?? null; $result = openssl_pkey_export($private_key, $private_key_pem); if (! $result || empty($public_key_pem) || empty($private_key_pem)) { throw new Exception($error_message); } return [ 'public' => $public_key_pem, 'private' => $private_key_pem, ]; } }