From 4bd9654fe71ca386e0f6b2b9daa83d41bac44781 Mon Sep 17 00:00:00 2001
From: Efe <hbehar@syncad.com>
Date: Tue, 22 Nov 2022 11:48:08 +0100
Subject: [PATCH] WIP Catch and process oauth request for openhive chat

---
 config/default.json                      |  3 ++-
 src/app/components/modules/LoginForm.jsx | 12 ++++++++++--
 src/app/redux/UserSaga.js                | 23 +++++++++++++++++++++++
 src/server/server.js                     | 18 ++++++++++++++++++
 4 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/config/default.json b/config/default.json
index 1009e2cd6..232197ae4 100644
--- a/config/default.json
+++ b/config/default.json
@@ -57,5 +57,6 @@
     "max_fee_referrer": 300,
     "max_fee_creator": 100,
     "max_fee_provider": 100
-  }
+  },
+  "opehive_oauth_origin": "https://openhive.chat" 
 }
diff --git a/src/app/components/modules/LoginForm.jsx b/src/app/components/modules/LoginForm.jsx
index 086ffdf55..5b3979325 100644
--- a/src/app/components/modules/LoginForm.jsx
+++ b/src/app/components/modules/LoginForm.jsx
@@ -73,6 +73,8 @@ class LoginForm extends Component {
         if (this.refs.username && !this.refs.username.value) this.refs.username.focus();
         // eslint-disable-next-line react/no-string-refs
         if (this.refs.username && this.refs.username.value) this.refs.pw.focus();
+
+        this.registerOauthRequest();
     }
 
     componentDidUpdate() {
@@ -143,6 +145,14 @@ class LoginForm extends Component {
         });
     };
 
+
+    registerOauthRequest = () => {
+        const params = new URLSearchParams(window.location.search);
+        if (params.has('redirect_uri') && params.get('scope') === 'login' && params.has('state')) {
+            sessionStorage.setItem('oauth', decodeURIComponent( params.toString()));
+        }
+    }
+
     loginWithHiveSigner = () => {
         const path = window.location.pathname;
         if (path === '/login/hivesigner') {
@@ -695,9 +705,7 @@ export default connect(
             afterLoginRedirectToWelcome
         ) => {
             const { type } = loginBroadcastOperation ? loginBroadcastOperation.toJS() : {};
-
             serverApiRecordEvent('SignIn', type);
-            console.log('really submit');
             dispatch(
                 userActions.usernamePasswordLogin({
                     username,
diff --git a/src/app/redux/UserSaga.js b/src/app/redux/UserSaga.js
index 32f920692..e6f9855b4 100644
--- a/src/app/redux/UserSaga.js
+++ b/src/app/redux/UserSaga.js
@@ -530,6 +530,29 @@ function* usernamePasswordLogin2(options) {
 
             console.log('Logging in as', username);
             const response = yield serverApiLogin(username, signatures);
+
+
+            // Check if there is an ongoing oauth process
+            // if yes, generate a token and redirect
+            // TODO: still it is unknown why this is not satisfying rocket.chat
+            // TODO: also figure out why rocket.chat doesn't come back for the last
+            // token exchange step for retrieving access_token.
+            if (sessionStorage.getItem('oauth')) {
+                try {
+                    const params = new URLSearchParams(sessionStorage.getItem('oauth'));
+                    const msg = { authors: [username], timestamp: Date.now(), signed_message: 'login' };
+                    const h = hash.sha256(JSON.stringify(msg));
+                    const signature = Signature.sign(h, private_keys.get('posting_private'));
+                    const code = Buffer.from(signature.toHex(), 'hex').toString('base64');
+                    const url = params.get('redirect_uri') + '?code=' + code + '&state=' + params.get('state') + '&username=' + username;
+
+                    window.location.href = url;
+                    sessionStorage.removeItem('oauth');
+                } catch (err) {
+                    sessionStorage.removeItem('oauth');
+                }
+            }
+
             yield response.data;
         }
     } catch (error) {
diff --git a/src/server/server.js b/src/server/server.js
index 19e258ee9..7f1d885df 100644
--- a/src/server/server.js
+++ b/src/server/server.js
@@ -116,6 +116,24 @@ app.use(async (ctx, next) => {
         return;
     }
 
+    if (ctx.method === 'GET' && ['/oauth/authorize', '/oauth/token'].includes(ctx.URL.pathname)) {
+        // TODO: strictly check if incoming origin is "opehive_oauth_origin" from config
+        const params = new URLSearchParams(ctx.URL.search);
+        if (!params.has('state') && !params.has('redirect_uri') && !params.has('scope')) {
+            ctx.redirect('/');
+            return;
+        }
+
+        ctx.redirect('/login.html?' + params.toString());
+        return;
+    }
+    // openhive.chat token exchange
+    if (ctx.method === 'GET' && ctx.URL.pathname === '/oauth/token') {
+        const params = new URLSearchParams(ctx.URL.search);
+        console.log(params);
+        return;
+    }
+
     // redirect to home page/feed if known account
     if (ctx.method === 'GET' && ctx.url === '/' && ctx.session.a) {
         ctx.status = 302;
-- 
GitLab