File u_added_jwt_tokens_capability.patch of Package python-websockify

From 6dc9005930798873ffa714d184312aafd0209503 Mon Sep 17 00:00:00 2001
From: UXabre <arend.lapere@gmail.com>
Date: Thu, 17 Jan 2019 08:53:01 -0500
Subject: [PATCH] Added JWT/JWS/JWE tokens capability

---
 test-requirements.txt        |  1 +
 tests/fixtures/private.pem   | 27 +++++++++++
 tests/fixtures/public.pem    |  9 ++++
 tests/fixtures/symmetric.key |  1 +
 tests/test_websocketproxy.py | 90 ++++++++++++++++++++++++++++++++++++
 websockify/token_plugins.py  | 46 ++++++++++++++++++
 6 files changed, 174 insertions(+)
 create mode 100644 tests/fixtures/private.pem
 create mode 100644 tests/fixtures/public.pem
 create mode 100644 tests/fixtures/symmetric.key

diff --git a/websockify/token_plugins.py b/websockify/token_plugins.py
index e87dcd0..45e974c 100644
--- a/websockify/token_plugins.py
+++ b/websockify/token_plugins.py
@@ -87,3 +87,49 @@ class JSONTokenApi(BaseTokenAPI):
     def process_result(self, resp):
         resp_json = resp.json()
         return (resp_json['host'], resp_json['port'])
+
+
+class JWTTokenApi(BasePlugin):
+    # source is a JWT-token, with hostname and port included
+    # Both JWS as JWE tokens are accepted. With regards to JWE tokens, the key is re-used for both validation and decryption.
+
+    def lookup(self, token):
+        try:
+            from jwcrypto import jwt
+            import json
+
+            key = jwt.JWK()
+            
+            try:
+                with open(self.source, 'rb') as key_file:
+                    key_data = key_file.read()
+            except Exception as e:
+                print >>sys.stderr, "Error loading key file: %s" % (e)
+                return None
+
+            try:
+                key.import_from_pem(key_data)
+            except:
+                try:
+                    key.import_key(k=key_data,kty='oct')
+                except:
+                    print >>sys.stderr, 'Failed to correctly parse key data!'
+                    return None
+
+            try:
+                token = jwt.JWT(key=key, jwt=token)
+                parsed_header = json.loads(token.header)
+
+                if 'enc' in parsed_header:
+                    # Token is encrypted, so we need to decrypt by passing the claims to a new instance
+                    token = jwt.JWT(key=key, jwt=token.claims)
+
+                parsed = json.loads(token.claims)
+
+                return (parsed['host'], parsed['port'])
+            except Exception as e:
+                print >>sys.stderr, "Failed to parse token: %s" % (e) 
+                return None
+        except ImportError as e:
+            print >>sys.stderr, "package jwcrypto not found, are you sure you've installed it correctly?" 
+            return None
openSUSE Build Service is sponsored by