From 70e972ff7d90c10011de7771c09e821595f38c57 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Fri, 10 Jan 2020 14:26:06 -0600 Subject: [PATCH] Revert ":twisted_rightwards_arrows: Merge branch 'oauth-support' of https://github.com/tildabio/n8n" This reverts commit 0c5972bb9873c3eccbf116eb26c895dd1518324f, reversing changes made to 3de03b5097396a227765829120da936837cb7f23. --- packages/cli/commands/start.ts | 2 +- packages/cli/nodemon.json | 4 +- packages/cli/package.json | 2 - packages/cli/src/Server.ts | 135 ------------------ packages/editor-ui/src/Interface.ts | 2 - .../src/components/CredentialsList.vue | 20 +-- .../src/components/mixins/restApi.ts | 15 -- packages/editor-ui/src/router.ts | 6 - packages/editor-ui/vue.config.js | 1 - .../credentials/OAuth2Api.credentials.ts | 56 -------- packages/nodes-base/nodes/OAuth.node.ts | 104 -------------- packages/nodes-base/package.json | 6 +- 12 files changed, 7 insertions(+), 346 deletions(-) delete mode 100644 packages/nodes-base/credentials/OAuth2Api.credentials.ts delete mode 100644 packages/nodes-base/nodes/OAuth.node.ts diff --git a/packages/cli/commands/start.ts b/packages/cli/commands/start.ts index e8f1694b9e..5494b5c5c3 100644 --- a/packages/cli/commands/start.ts +++ b/packages/cli/commands/start.ts @@ -176,7 +176,7 @@ export class Start extends Command { Start.openBrowser(); } this.log(`\nPress "o" to open in Browser.`); - process.stdin.on("data", (key: string) => { + process.stdin.on("data", (key) => { if (key === 'o') { Start.openBrowser(); inputText = ''; diff --git a/packages/cli/nodemon.json b/packages/cli/nodemon.json index 5bdb290fb2..efb39c6667 100644 --- a/packages/cli/nodemon.json +++ b/packages/cli/nodemon.json @@ -9,6 +9,6 @@ "index.ts", "src" ], - "exec": "npm run build && npm start", + "exec": "npm start", "ext": "ts" -} +} \ No newline at end of file diff --git a/packages/cli/package.json b/packages/cli/package.json index f3fdb87bcd..273418fda1 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -78,11 +78,9 @@ "basic-auth": "^2.0.1", "body-parser": "^1.18.3", "body-parser-xml": "^1.1.0", - "client-oauth2": "^4.2.5", "compression": "^1.7.4", "connect-history-api-fallback": "^1.6.0", "convict": "^5.0.0", - "csrf": "^3.1.0", "dotenv": "^8.0.0", "express": "^4.16.4", "flatted": "^2.0.0", diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index 9eecf67062..8fff1ef217 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -10,9 +10,6 @@ import * as bodyParser from 'body-parser'; require('body-parser-xml')(bodyParser); import * as history from 'connect-history-api-fallback'; import * as requestPromise from 'request-promise-native'; -import * as _ from 'lodash'; -import * as clientOAuth2 from 'client-oauth2'; -import * as csrf from 'csrf'; import { ActiveExecutions, @@ -732,8 +729,6 @@ class App { // Encrypt the data const credentials = new Credentials(incomingData.name, incomingData.type, incomingData.nodesAccess); - _.unset(incomingData.data, 'csrfSecret'); - _.unset(incomingData.data, 'oauthTokenData'); credentials.setData(incomingData.data, encryptionKey); const newCredentialsData = credentials.getDataToSave() as unknown as ICredentialsDb; @@ -853,138 +848,8 @@ class App { return returnData; })); - // ---------------------------------------- - // OAuth2-Credential/Auth - // ---------------------------------------- - // Returns all the credential types which are defined in the loaded n8n-modules - this.app.get('/rest/oauth2-credential/auth', ResponseHelper.send(async (req: express.Request, res: express.Response): Promise => { - if (req.query.id === undefined) { - throw new Error('Required credential id is missing!'); - } - - const result = await Db.collections.Credentials!.findOne(req.query.id); - if (result === undefined) { - res.status(404).send('The credential is not known.'); - return ''; - } - - let encryptionKey = undefined; - encryptionKey = await UserSettings.getEncryptionKey(); - if (encryptionKey === undefined) { - throw new Error('No encryption key got found to decrypt the credentials!'); - } - - const credentials = new Credentials(result.name, result.type, result.nodesAccess, result.data); - (result as ICredentialsDecryptedDb).data = credentials.getData(encryptionKey!); - (result as ICredentialsDecryptedResponse).id = result.id.toString(); - - const oauthCredentials = (result as ICredentialsDecryptedDb).data; - if (oauthCredentials === undefined) { - throw new Error('Unable to read OAuth credentials'); - } - - let token = new csrf(); - // Generate a CSRF prevention token and send it as a OAuth2 state stringma/ERR - oauthCredentials.csrfSecret = token.secretSync(); - const state = { - 'token': token.create(oauthCredentials.csrfSecret), - 'cid': req.query.id - } - const stateEncodedStr = Buffer.from(JSON.stringify(state)).toString('base64') as string; - - const oAuthObj = new clientOAuth2({ - clientId: _.get(oauthCredentials, 'clientId') as string, - clientSecret: _.get(oauthCredentials, 'clientSecret', '') as string, - accessTokenUri: _.get(oauthCredentials, 'accessTokenUrl', '') as string, - authorizationUri: _.get(oauthCredentials, 'authUrl', '') as string, - redirectUri: _.get(oauthCredentials, 'callbackUrl', WebhookHelpers.getWebhookBaseUrl()) as string, - scopes: _.split(_.get(oauthCredentials, 'scope', 'openid,') as string, ','), - state: stateEncodedStr - }); - - credentials.setData(oauthCredentials, encryptionKey); - const newCredentialsData = credentials.getDataToSave() as unknown as ICredentialsDb; - - // Add special database related data - newCredentialsData.updatedAt = this.getCurrentDate(); - - // Update the credentials in DB - await Db.collections.Credentials!.update(req.query.id, newCredentialsData); - - return oAuthObj.code.getUri(); - })); - - // ---------------------------------------- - // OAuth2-Credential/Callback - // ---------------------------------------- - - // Verify and store app code. Generate access tokens and store for respective credential. - this.app.get('/rest/oauth2-credential/callback', ResponseHelper.send(async (req: express.Request, res: express.Response): Promise => { - const {code, state: stateEncoded} = req.query; - if (code === undefined || stateEncoded === undefined) { - throw new Error('Insufficient parameters for OAuth2 callback') - } - - let state; - try { - state = JSON.parse(Buffer.from(stateEncoded, 'base64').toString()); - } catch (error) { - throw new Error('Invalid state format returned'); - } - - const result = await Db.collections.Credentials!.findOne(state.cid); - if (result === undefined) { - res.status(404).send('The credential is not known.'); - return ''; - } - - let encryptionKey = undefined; - encryptionKey = await UserSettings.getEncryptionKey(); - if (encryptionKey === undefined) { - throw new Error('No encryption key got found to decrypt the credentials!'); - } - - const credentials = new Credentials(result.name, result.type, result.nodesAccess, result.data); - (result as ICredentialsDecryptedDb).data = credentials.getData(encryptionKey!); - const oauthCredentials = (result as ICredentialsDecryptedDb).data; - if (oauthCredentials === undefined) { - throw new Error('Unable to read OAuth credentials'); - } - - let token = new csrf(); - if (oauthCredentials.csrfSecret === undefined || !token.verify(oauthCredentials.csrfSecret as string, state.token)) { - res.status(404).send('The OAuth2 callback state is invalid.'); - return ''; - } - - const oAuthObj = new clientOAuth2({ - clientId: _.get(oauthCredentials, 'clientId') as string, - clientSecret: _.get(oauthCredentials, 'clientSecret', '') as string, - accessTokenUri: _.get(oauthCredentials, 'accessTokenUrl', '') as string, - authorizationUri: _.get(oauthCredentials, 'authUrl', '') as string, - redirectUri: _.get(oauthCredentials, 'callbackUrl', WebhookHelpers.getWebhookBaseUrl()) as string, - scopes: _.split(_.get(oauthCredentials, 'scope', 'openid,') as string, ',') - }); - - const oauthToken = await oAuthObj.code.getToken(req.originalUrl); - if (oauthToken === undefined) { - throw new Error('Unable to get access tokens'); - } - - oauthCredentials.oauthTokenData = JSON.stringify(oauthToken.data); - _.unset(oauthCredentials, 'csrfSecret'); - credentials.setData(oauthCredentials, encryptionKey); - const newCredentialsData = credentials.getDataToSave() as unknown as ICredentialsDb; - // Add special database related data - newCredentialsData.updatedAt = this.getCurrentDate(); - // Save the credentials in DB - await Db.collections.Credentials!.update(state.cid, newCredentialsData); - - return 'Success!'; - })); - // ---------------------------------------- // Executions // ---------------------------------------- diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index a79ebdd8fd..e6e34fb9d5 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -145,8 +145,6 @@ export interface IRestApi { deleteExecutions(sendData: IExecutionDeleteFilter): Promise; retryExecution(id: string, loadWorkflow?: boolean): Promise; getTimezones(): Promise; - OAuth2CredentialAuthorize(sendData: ICredentialsResponse): Promise; - OAuth2Callback(code: string, state: string): Promise; } export interface IBinaryDisplayData { diff --git a/packages/editor-ui/src/components/CredentialsList.vue b/packages/editor-ui/src/components/CredentialsList.vue index eeece990bc..758adf1a4c 100644 --- a/packages/editor-ui/src/components/CredentialsList.vue +++ b/packages/editor-ui/src/components/CredentialsList.vue @@ -25,12 +25,10 @@ + width="120"> @@ -93,20 +91,6 @@ export default mixins( this.editCredentials = null; this.credentialEditDialogVisible = true; }, - async OAuth2CredentialAuthorize (credential: ICredentialsResponse) { - let url; - try { - url = await this.restApi().OAuth2CredentialAuthorize(credential) as string; - } catch (error) { - this.$showError(error, 'OAuth Authorization Error', 'Error generating authorization URL:'); - return; - } - - const params = `scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,width=0,height=0,left=-1000,top=-1000`; - const oauthPopup = window.open(url, 'OAuth2 Authorization', params); - - console.log(oauthPopup); - }, editCredential (credential: ICredentialsResponse) { const editCredentials = { id: credential.id, @@ -140,7 +124,7 @@ export default mixins( try { this.credentials = JSON.parse(JSON.stringify(this.$store.getters.allCredentials)); } catch (error) { - this.$showError(error, 'Problem loading credentials', 'There was a problem loading the credentials:'); + this.$showError(error, 'Proble loading credentials', 'There was a problem loading the credentials:'); this.isDataLoading = false; return; } diff --git a/packages/editor-ui/src/components/mixins/restApi.ts b/packages/editor-ui/src/components/mixins/restApi.ts index 72616e83d4..a72520718e 100644 --- a/packages/editor-ui/src/components/mixins/restApi.ts +++ b/packages/editor-ui/src/components/mixins/restApi.ts @@ -252,21 +252,6 @@ export const restApi = Vue.extend({ return self.restApi().makeRestApiRequest('GET', `/credential-types`); }, - // Get OAuth2 Authorization URL using the stored credentials - OAuth2CredentialAuthorize: (sendData: ICredentialsResponse): Promise => { - return self.restApi().makeRestApiRequest('GET', `/oauth2-credential/auth`, sendData); - }, - - // Verify OAuth2 provider callback and kick off token generation - OAuth2Callback: (code: string, state: string): Promise => { - const sendData = { - 'code': code, - 'state': state, - }; - - return self.restApi().makeRestApiRequest('POST', `/oauth2-credential/callback`, sendData); - }, - // Returns the execution with the given name getExecution: async (id: string): Promise => { const response = await self.restApi().makeRestApiRequest('GET', `/executions/${id}`); diff --git a/packages/editor-ui/src/router.ts b/packages/editor-ui/src/router.ts index f33d028f94..14a31c7e80 100644 --- a/packages/editor-ui/src/router.ts +++ b/packages/editor-ui/src/router.ts @@ -19,12 +19,6 @@ export default new Router({ sidebar: MainSidebar, }, }, - { - path: '/oauth2/callback', - name: 'OAuth2Callback', - components: { - }, - }, { path: '/workflow', name: 'NodeViewNew', diff --git a/packages/editor-ui/vue.config.js b/packages/editor-ui/vue.config.js index b47e0c4b23..f70f41c5b2 100644 --- a/packages/editor-ui/vue.config.js +++ b/packages/editor-ui/vue.config.js @@ -12,7 +12,6 @@ module.exports = { }, }, configureWebpack: { - devtool: 'source-map', plugins: [ new GoogleFontsPlugin({ fonts: [ diff --git a/packages/nodes-base/credentials/OAuth2Api.credentials.ts b/packages/nodes-base/credentials/OAuth2Api.credentials.ts deleted file mode 100644 index 452fdb8f57..0000000000 --- a/packages/nodes-base/credentials/OAuth2Api.credentials.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { - ICredentialType, - NodePropertyTypes, -} from 'n8n-workflow'; - - -export class OAuth2Api implements ICredentialType { - name = 'OAuth2Api'; - displayName = 'OAuth2 API'; - properties = [ - { - displayName: 'Authorization URL', - name: 'authUrl', - type: 'string' as NodePropertyTypes, - default: '', - required: true, - }, - { - displayName: 'Access Token URL', - name: 'accessTokenUrl', - type: 'string' as NodePropertyTypes, - default: '', - required: true, - }, - { - displayName: 'Callback URL', - name: 'callbackUrl', - type: 'string' as NodePropertyTypes, - default: '', - required: true, - }, - { - displayName: 'Client ID', - name: 'clientId', - type: 'string' as NodePropertyTypes, - default: '', - required: true, - }, - { - displayName: 'Client Secret', - name: 'clientSecret', - type: 'string' as NodePropertyTypes, - typeOptions: { - password: true, - }, - default: '', - required: true, - }, - { - displayName: 'Scope', - name: 'scope', - type: 'string' as NodePropertyTypes, - default: '', - }, - ]; -} diff --git a/packages/nodes-base/nodes/OAuth.node.ts b/packages/nodes-base/nodes/OAuth.node.ts deleted file mode 100644 index 189ae9e408..0000000000 --- a/packages/nodes-base/nodes/OAuth.node.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { IExecuteFunctions } from 'n8n-core'; -import { - GenericValue, - IDataObject, - INodeExecutionData, - INodeType, - INodeTypeDescription, -} from 'n8n-workflow'; - -import { set } from 'lodash'; - -import * as util from 'util'; -import { connectionFields } from './ActiveCampaign/ConnectionDescription'; - -export class OAuth implements INodeType { - description: INodeTypeDescription = { - displayName: 'OAuth', - name: 'oauth', - icon: 'fa:code-branch', - group: ['input'], - version: 1, - description: 'Gets, sends data to Oauth API Endpoint and receives generic information.', - defaults: { - name: 'OAuth', - color: '#0033AA', - }, - inputs: ['main'], - outputs: ['main'], - credentials: [ - { - name: 'OAuth2Api', - required: true, - } - ], - properties: [ - { - displayName: 'Operation', - name: 'operation', - type: 'options', - options: [ - { - name: 'Get', - value: 'get', - description: 'Returns the value of a key from oauth.', - }, - ], - default: 'get', - description: 'The operation to perform.', - }, - - // ---------------------------------- - // get - // ---------------------------------- - { - displayName: 'Name', - name: 'propertyName', - type: 'string', - displayOptions: { - show: { - operation: [ - 'get' - ], - }, - }, - default: 'propertyName', - required: true, - description: 'Name of the property to write received data to.
Supports dot-notation.
Example: "data.person[0].name"', - }, - ] - }; - - async execute(this: IExecuteFunctions): Promise { - const credentials = this.getCredentials('OAuth2Api'); - if (credentials === undefined) { - throw new Error('No credentials got returned!'); - } - - if (credentials.oauthTokenData === undefined) { - throw new Error('OAuth credentials not connected'); - } - - const operation = this.getNodeParameter('operation', 0) as string; - if (operation === 'get') { - const items = this.getInputData(); - const returnItems: INodeExecutionData[] = []; - - let item: INodeExecutionData; - - // credentials.oauthTokenData has the refreshToken and accessToken available - // it would be nice to have credentials.getOAuthToken() which returns the accessToken - // and also handles an error case where if the token is to be refreshed, it does so - // without knowledge of the node. - console.log('Got OAuth credentials!', credentials.oauthTokenData); - - for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { - item = { json: { itemIndex } }; - returnItems.push(item); - } - return [returnItems]; - } else { - throw new Error('Unknown operation'); - } - } -} diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index a91be93fb6..a139598bd2 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -58,7 +58,6 @@ "dist/credentials/MySql.credentials.js", "dist/credentials/NextCloudApi.credentials.js", "dist/credentials/OpenWeatherMapApi.credentials.js", - "dist/credentials/OAuth2Api.credentials.js", "dist/credentials/PipedriveApi.credentials.js", "dist/credentials/Postgres.credentials.js", "dist/credentials/PayPalApi.credentials.js", @@ -135,11 +134,10 @@ "dist/nodes/MoveBinaryData.node.js", "dist/nodes/MongoDb/MongoDb.node.js", "dist/nodes/MySql/MySql.node.js", - "dist/nodes/NextCloud/NextCloud.node.js", - "dist/nodes/Mandrill/Mandrill.node.js", + "dist/nodes/NextCloud/NextCloud.node.js", + "dist/nodes/Mandrill/Mandrill.node.js", "dist/nodes/NoOp.node.js", "dist/nodes/OpenWeatherMap.node.js", - "dist/nodes/OAuth.node.js", "dist/nodes/Pipedrive/Pipedrive.node.js", "dist/nodes/Pipedrive/PipedriveTrigger.node.js", "dist/nodes/Postgres/Postgres.node.js",