From 941d423117d0031251683765b926c029aa263392 Mon Sep 17 00:00:00 2001
From: Sonia Zorba <sonia.zorba@inaf.it>
Date: Thu, 13 May 2021 13:47:45 +0200
Subject: [PATCH] Removed support for external JWKS (used by old portals)

---
 classes/JWKSHandler.php                    | 61 ----------------------
 classes/TokenExchanger.php                 | 58 +-------------------
 classes/UserHandler.php                    |  2 +-
 classes/datalayer/JWKSDAO.php              |  4 --
 classes/datalayer/mysql/MySQLJWKSDAO.php   | 44 ----------------
 classes/model/BrowserBasedOAuth2Client.php |  2 -
 classes/model/PublicJWK.php                | 12 -----
 config-example.yaml                        |  2 -
 8 files changed, 3 insertions(+), 182 deletions(-)
 delete mode 100644 classes/model/PublicJWK.php

diff --git a/classes/JWKSHandler.php b/classes/JWKSHandler.php
index 2f2d5bc..feffd90 100644
--- a/classes/JWKSHandler.php
+++ b/classes/JWKSHandler.php
@@ -77,65 +77,4 @@ class JWKSHandler {
         return $matches[1];
     }
 
-    public function loadAllJWKS(): array {
-
-        foreach ($this->locator->getBrowserBasedOAuth2Clients() as $client) {
-            if ($client->jwks !== null) {
-                $this->loadJWKS($client->jwks);
-            }
-        }
-
-        $dao = $this->locator->getJWKSDAO();
-        return $dao->getAllPublicJWK();
-    }
-
-    private function loadJWKS($url) {
-
-        $dao = $this->locator->getJWKSDAO();
-
-        $conn = curl_init($url);
-        curl_setopt($conn, CURLOPT_FOLLOWLOCATION, 1);
-        curl_setopt($conn, CURLOPT_RETURNTRANSFER, true);
-
-        $result = curl_exec($conn);
-        $info = curl_getinfo($conn);
-
-        if ($info['http_code'] === 200) {
-            $jwks = json_decode($result, TRUE);
-
-            foreach ($jwks['keys'] as $key) {
-                $key['url'] = $url;
-                $jwk = $this->getPublicJWK($key);
-                $dao->updatePublicJWK($jwk);
-            }
-        } else {
-            error_log('Error while retrieving JWKS from ' . $url);
-        }
-
-        curl_close($conn);
-    }
-
-    private function getPublicJWK($data): PublicJWK {
-
-        // Convert Base64 uri-safe variant to default (needed for JWKS)
-        $n = strtr($data['n'], '-_', '+/');
-
-        $rsa = new RSA();
-
-        $key = "<RSAKeyPair>"
-                . "<Modulus>" . $n . "</Modulus>"
-                . "<Exponent>" . $data['e'] . "</Exponent>"
-                . "</RSAKeyPair>";
-
-        $rsa->loadKey($key, RSA::PUBLIC_FORMAT_XML);
-
-        $jwk = new PublicJWK();
-        $jwk->kid = $data['kid'];
-        $jwk->key = $rsa;
-        $jwk->url = $data['url'];
-        $jwk->updateTime = time();
-
-        return $jwk;
-    }
-
 }
diff --git a/classes/TokenExchanger.php b/classes/TokenExchanger.php
index 8aa7ac9..fce83c9 100644
--- a/classes/TokenExchanger.php
+++ b/classes/TokenExchanger.php
@@ -24,8 +24,6 @@
 
 namespace RAP;
 
-use \Firebase\JWT\JWT;
-
 /**
  * See https://tools.ietf.org/html/rfc8693
  */
@@ -70,9 +68,9 @@ class TokenExchanger {
         if ($params['expires_in'] !== null) {
             $claims['exp'] = time() + intval($params['expires_in']);
         }
-        
+
         $accessToken = $this->locator->getTokenBuilder()->generateToken($claims);
-        
+
         $data = [];
 
         $data['access_token'] = $accessToken;
@@ -92,56 +90,4 @@ class TokenExchanger {
         return $audiences;
     }
 
-    /**
-     * DEPRECATED (currently used by portals: to be removed)
-     */
-    public function exchangeTokenOld(string $token) {
-
-        $key = $this->getExternalKeyForToken($token);
-        $decoded = JWT::decode($token, $key->key, ['RS256']);
-
-        $subject = $decoded->sub;
-        $lifespan = ($decoded->exp - time());
-
-        $data = [];
-
-        $data['access_token'] = $this->locator->getTokenBuilder()->generateNewToken($subject, $lifespan / 3600, "gms");
-        $data['issued_token_type'] = "urn:ietf:params:oauth:token-type:access_token";
-        $data['token_type'] = 'Bearer';
-        $data['expires_in'] = $lifespan;
-
-        return $data;
-    }
-
-    private function getExternalKeyForToken(string $token): PublicJWK {
-
-        $keys = $this->locator->getJWKSDAO()->getAllPublicJWK();
-
-        $parts = explode('.', $token);
-        $head = JWT::jsonDecode(JWT::urlsafeB64Decode($parts[0]));
-
-        $kid = $head->kid;
-
-        $key = $this->getKeyByKid($keys, $kid);
-        if ($key === null) {
-            $keys = $this->locator->getJWKSHandler()->loadAllJWKS();
-        }
-        $key = $this->getKeyByKid($keys, $kid);
-
-        if ($key !== null) {
-            return $key;
-        }
-
-        throw new \Exception("Invalid kid");
-    }
-
-    private function getKeyByKid(array $keys, string $kid): ?PublicJWK {
-        foreach ($keys as $key) {
-            if ($key->kid === $kid) {
-                return $key;
-            }
-        }
-        return null;
-    }
-
 }
diff --git a/classes/UserHandler.php b/classes/UserHandler.php
index 9d8f573..8f27522 100644
--- a/classes/UserHandler.php
+++ b/classes/UserHandler.php
@@ -102,7 +102,7 @@ class UserHandler {
             return $this->joinNewIdentity($user1, $user2);
         }
 
-        // Call Grouper for moving groups and privileges from one user to the other
+        // Call GMS for moving groups and privileges from one user to the other
         $remainingUserId = $this->locator->getGmsClient()->joinGroups($userId1, $userId2);
 
         $remainingUser = $userId1 === $remainingUserId ? $user1 : $user2;
diff --git a/classes/datalayer/JWKSDAO.php b/classes/datalayer/JWKSDAO.php
index a5b52a6..9cd83f4 100644
--- a/classes/datalayer/JWKSDAO.php
+++ b/classes/datalayer/JWKSDAO.php
@@ -11,8 +11,4 @@ interface JWKSDAO {
     public function insertRSAKeyPair(RSAKeyPair $keyPair): RSAKeyPair;
 
     public function getNewestKeyPair(): ?RSAKeyPair;
-
-    public function getAllPublicJWK(): array;
-
-    public function updatePublicJWK(PublicJWK $jwk);
 }
diff --git a/classes/datalayer/mysql/MySQLJWKSDAO.php b/classes/datalayer/mysql/MySQLJWKSDAO.php
index 5611db6..8e7a83a 100644
--- a/classes/datalayer/mysql/MySQLJWKSDAO.php
+++ b/classes/datalayer/mysql/MySQLJWKSDAO.php
@@ -85,48 +85,4 @@ class MySQLJWKSDAO extends BaseMySQLDAO implements JWKSDAO {
         return $keyPair;
     }
 
-    public function getAllPublicJWK(): array {
-
-        $dbh = $this->getDBHandler();
-
-        $query = "SELECT `kid`, `key`, `url`, `update_time` FROM public_jwk";
-
-        $stmt = $dbh->prepare($query);
-        $stmt->execute();
-
-        $keys = [];
-
-        foreach ($stmt->fetchAll() as $row) {
-            array_push($keys, $this->getPublicJWKFromResultRow($row));
-        }
-
-        return $keys;
-    }
-
-    private function getPublicJWKFromResultRow($row): PublicJWK {
-
-        $jwk = new PublicJWK ();
-        $jwk->key = $row['key'];
-        $jwk->kid = $row['kid'];
-        $jwk->url = $row['url'];
-        $jwk->updateTime = $row['update_time'];
-        return $jwk;
-    }
-
-    public function updatePublicJWK(PublicJWK $jwk) {
-
-        $dbh = $this->getDBHandler();
-
-        $query = "INSERT INTO public_jwk(kid, `key`, `url`, update_time) VALUES (:kid, :key, :url, :update_time)"
-                . " ON DUPLICATE KEY UPDATE `key`=:key, `url`=:url, update_time=:update_time";
-
-        $stmt = $dbh->prepare($query);
-        $stmt->bindParam(':kid', $jwk->kid);
-        $stmt->bindParam(':key', $jwk->key);
-        $stmt->bindParam(':url', $jwk->url);
-        $stmt->bindParam(':update_time', $jwk->updateTime);
-
-        $stmt->execute();
-    }
-
 }
diff --git a/classes/model/BrowserBasedOAuth2Client.php b/classes/model/BrowserBasedOAuth2Client.php
index b4ffa12..6edad89 100644
--- a/classes/model/BrowserBasedOAuth2Client.php
+++ b/classes/model/BrowserBasedOAuth2Client.php
@@ -35,7 +35,6 @@ class BrowserBasedOAuth2Client extends BrowserBasedClient {
     public $scope;
     public $homePage;
     public $showInHome;
-    public $jwks;
     public $scopeAudienceMap = [];
 
     public function __construct(object $config) {
@@ -48,7 +47,6 @@ class BrowserBasedOAuth2Client extends BrowserBasedClient {
         $this->homePage = isset($config->home) ? $config->home : null;
         $this->showInHome = isset($config->showInHome) ? $config->showInHome : false;
         $this->authMethods = $config->methods;
-        $this->jwks = isset($config->jwks) ? $config->jwks : null;
         $this->scopeAudienceMap = isset($config->scopeAudienceMap) ? $config->scopeAudienceMap : null;
     }
 
diff --git a/classes/model/PublicJWK.php b/classes/model/PublicJWK.php
deleted file mode 100644
index c883bf5..0000000
--- a/classes/model/PublicJWK.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-namespace RAP;
-
-class PublicJWK {
-
-    public $kid;
-    public $key;
-    public $url;
-    public $updateTime;
-
-}
diff --git a/config-example.yaml b/config-example.yaml
index 87b2554..fb4208a 100644
--- a/config-example.yaml
+++ b/config-example.yaml
@@ -59,7 +59,6 @@ clients:
     icon: 
     showInHome: true
     methods: [eduGAIN, Google, Facebook, LinkedIn, X.509, LocalIdP]
-    jwks:
   - label: "Asiago Astrophysical Observatory (localhost)"
     id: aao-dev
     secret: 2a97516c354b68848cdbd8f54a226a0a55b21ed138e207ad6c5cbb9c00aa5aea
@@ -69,7 +68,6 @@ clients:
     icon: asiago.gif
     showInHome: true
     methods: [eduGAIN, Google, Facebook, LinkedIn, X.509, LocalIdP]
-    jwks: http://localhost:8081/aao/jwks
 cliClients:
   - id: gms_cli
     secret: 2a97516c354b68848cdbd8f54a226a0a55b21ed138e207ad6c5cbb9c00aa5aea
-- 
GitLab