From 5d3864696cf88ee4498b0c02d9c0cfcdc73ceb81 Mon Sep 17 00:00:00 2001 From: Andres Aguiar Date: Thu, 7 May 2020 15:10:37 -0300 Subject: [PATCH] remove account linking rules --- rules.json | 20 -- .../link-users-by-email-with-metadata.js | 83 ------- src/rules/link-users-by-email.js | 71 ------ .../link-users-by-email-with-metadata.test.js | 229 ------------------ test/rules/link-users-by-email.test.js | 205 ---------------- 5 files changed, 608 deletions(-) delete mode 100644 src/rules/link-users-by-email-with-metadata.js delete mode 100644 src/rules/link-users-by-email.js delete mode 100644 test/rules/link-users-by-email-with-metadata.test.js delete mode 100644 test/rules/link-users-by-email.test.js diff --git a/rules.json b/rules.json index 439cd371..1982e7f2 100644 --- a/rules.json +++ b/rules.json @@ -92,26 +92,6 @@ "description": "

This rule will only allow access to an app from a specific set of IP addresses

", "code": "function ipAddressWhitelist(user, context, callback) {\n const whitelist = ['1.2.3.4', '2.3.4.5']; // authorized IPs\n const userHasAccess = whitelist.some(function (ip) {\n return context.request.ip === ip;\n });\n\n if (!userHasAccess) {\n return callback(new Error('Access denied from this IP address.'));\n }\n\n return callback(null, user, context);\n}" }, - { - "id": "link-users-by-email-with-metadata", - "title": "Link Accounts with Same Email Address while Merging Metadata", - "overview": "Link any accounts that have the same email address while merging metadata.", - "categories": [ - "access control" - ], - "description": "

This rule will link any accounts that have the same email address while merging metadata.

", - "code": "function linkUsersByEmailWithMetadata(user, context, callback) {\n const request = require('request');\n const _ = require('lodash');\n\n // Check if email is verified, we shouldn't automatically\n // merge accounts if this is not the case.\n if (!user.email || !user.email_verified) {\n return callback(null, user, context);\n }\n\n const userApiUrl = auth0.baseUrl + '/users';\n const userSearchApiUrl = auth0.baseUrl + '/users-by-email';\n\n request({\n url: userSearchApiUrl,\n headers: {\n Authorization: 'Bearer ' + auth0.accessToken\n },\n qs: {\n email: user.email\n }\n },\n function (err, response, body) {\n if (err) return callback(err);\n if (response.statusCode !== 200) return callback(new Error(body));\n\n var data = JSON.parse(body);\n // Ignore non-verified users and current user, if present\n data = data.filter(function (u) {\n return u.email_verified && (u.user_id !== user.user_id);\n });\n\n if (data.length > 1) {\n return callback(new Error('[!] Rule: Multiple user profiles already exist - cannot select base profile to link with'));\n }\n if (data.length === 0) {\n console.log('[-] Skipping link rule');\n return callback(null, user, context);\n }\n\n const originalUser = data[0];\n const provider = user.identities[0].provider;\n const providerUserId = user.identities[0].user_id;\n const mergeCustomizer = function(objectValue, sourceValue){\n if (_.isArray(objectValue)){\n return sourceValue.concat(objectValue);\n }\n };\n const mergedUserMetadata = _.merge({}, user.user_metadata, originalUser.user_metadata, mergeCustomizer);\n const mergedAppMetadata = _.merge({}, user.app_metadata, originalUser.app_metadata, mergeCustomizer);\n \n auth0.users.updateAppMetadata(originalUser.user_id, mergedAppMetadata)\n .then(auth0.users.updateUserMetadata(originalUser.user_id, mergedUserMetadata))\n .then(function() {\n request.post({\n url: userApiUrl + '/' + originalUser.user_id + '/identities',\n headers: {\n Authorization: 'Bearer ' + auth0.accessToken\n },\n json: { provider: provider, user_id: String(providerUserId) }\n }, function (err, response, body) {\n if (response && response.statusCode >= 400) {\n return callback(new Error('Error linking account: ' + response.statusMessage));\n }\n context.primaryUser = originalUser.user_id;\n callback(null, user, context);\n });\n })\n .catch(function (err) {\n callback(err);\n });\n });\n}" - }, - { - "id": "link-users-by-email", - "title": "Link Accounts with Same Email Address", - "overview": "Link any accounts that have the same email address.", - "categories": [ - "access control" - ], - "description": "

This rule will link any accounts that have the same email address.

\n
\n

Note: When linking accounts, only the metadata of the target user is saved. If you want to merge the metadata of the two accounts you must do that manually. See the document on Linking Accounts for more details.

\n
", - "code": "function linkUsersByEmail(user, context, callback) {\n const request = require('request');\n // Check if email is verified, we shouldn't automatically\n // merge accounts if this is not the case.\n if (!user.email || !user.email_verified) {\n return callback(null, user, context);\n }\n const userApiUrl = auth0.baseUrl + '/users';\n const userSearchApiUrl = auth0.baseUrl + '/users-by-email';\n\n request({\n url: userSearchApiUrl,\n headers: {\n Authorization: 'Bearer ' + auth0.accessToken\n },\n qs: {\n email: user.email\n }\n },\n function(err, response, body) {\n if (err) return callback(err);\n if (response.statusCode !== 200) return callback(new Error(body));\n\n var data = JSON.parse(body);\n // Ignore non-verified users and current user, if present\n data = data.filter(function(u) {\n return u.email_verified && (u.user_id !== user.user_id);\n });\n\n if (data.length > 1) {\n return callback(new Error('[!] Rule: Multiple user profiles already exist - cannot select base profile to link with'));\n }\n if (data.length === 0) {\n console.log('[-] Skipping link rule');\n return callback(null, user, context);\n }\n\n const originalUser = data[0];\n const provider = user.identities[0].provider;\n const providerUserId = user.identities[0].user_id;\n\n request.post({\n url: userApiUrl + '/' + originalUser.user_id + '/identities',\n headers: {\n Authorization: 'Bearer ' + auth0.accessToken\n },\n json: {\n provider: provider,\n user_id: String(providerUserId)\n }\n }, function(err, response, body) {\n if (response.statusCode >= 400) {\n return callback(new Error('Error linking account: ' + response.statusMessage));\n }\n context.primaryUser = originalUser.user_id;\n callback(null, user, context);\n });\n });\n}" - }, { "id": "roles-creation", "title": "Set roles to a user", diff --git a/src/rules/link-users-by-email-with-metadata.js b/src/rules/link-users-by-email-with-metadata.js deleted file mode 100644 index 32d08d96..00000000 --- a/src/rules/link-users-by-email-with-metadata.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @title Link Accounts with Same Email Address while Merging Metadata - * @overview Link any accounts that have the same email address while merging metadata. - * @gallery true - * @category access control - * - * This rule will link any accounts that have the same email address while merging metadata. - * - */ - -function linkUsersByEmailWithMetadata(user, context, callback) { - const request = require('request'); - const _ = require('lodash'); - - // Check if email is verified, we shouldn't automatically - // merge accounts if this is not the case. - if (!user.email || !user.email_verified) { - return callback(null, user, context); - } - - const userApiUrl = auth0.baseUrl + '/users'; - const userSearchApiUrl = auth0.baseUrl + '/users-by-email'; - - request({ - url: userSearchApiUrl, - headers: { - Authorization: 'Bearer ' + auth0.accessToken - }, - qs: { - email: user.email - } - }, - function (err, response, body) { - if (err) return callback(err); - if (response.statusCode !== 200) return callback(new Error(body)); - - var data = JSON.parse(body); - // Ignore non-verified users and current user, if present - data = data.filter(function (u) { - return u.email_verified && (u.user_id !== user.user_id); - }); - - if (data.length > 1) { - return callback(new Error('[!] Rule: Multiple user profiles already exist - cannot select base profile to link with')); - } - if (data.length === 0) { - console.log('[-] Skipping link rule'); - return callback(null, user, context); - } - - const originalUser = data[0]; - const provider = user.identities[0].provider; - const providerUserId = user.identities[0].user_id; - const mergeCustomizer = function(objectValue, sourceValue){ - if (_.isArray(objectValue)){ - return sourceValue.concat(objectValue); - } - }; - const mergedUserMetadata = _.merge({}, user.user_metadata, originalUser.user_metadata, mergeCustomizer); - const mergedAppMetadata = _.merge({}, user.app_metadata, originalUser.app_metadata, mergeCustomizer); - - auth0.users.updateAppMetadata(originalUser.user_id, mergedAppMetadata) - .then(auth0.users.updateUserMetadata(originalUser.user_id, mergedUserMetadata)) - .then(function() { - request.post({ - url: userApiUrl + '/' + originalUser.user_id + '/identities', - headers: { - Authorization: 'Bearer ' + auth0.accessToken - }, - json: { provider: provider, user_id: String(providerUserId) } - }, function (err, response, body) { - if (response && response.statusCode >= 400) { - return callback(new Error('Error linking account: ' + response.statusMessage)); - } - context.primaryUser = originalUser.user_id; - callback(null, user, context); - }); - }) - .catch(function (err) { - callback(err); - }); - }); -} diff --git a/src/rules/link-users-by-email.js b/src/rules/link-users-by-email.js deleted file mode 100644 index 336fe2e4..00000000 --- a/src/rules/link-users-by-email.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @title Link Accounts with Same Email Address - * @overview Link any accounts that have the same email address. - * @gallery true - * @category access control - * - * This rule will link any accounts that have the same email address. - * - * > Note: When linking accounts, only the metadata of the target user is saved. If you want to merge the metadata of the two accounts you must do that manually. See the document on [Linking Accounts](https://auth0.com/docs/link-accounts) for more details. - * - */ - -function linkUsersByEmail(user, context, callback) { - const request = require('request'); - // Check if email is verified, we shouldn't automatically - // merge accounts if this is not the case. - if (!user.email || !user.email_verified) { - return callback(null, user, context); - } - const userApiUrl = auth0.baseUrl + '/users'; - const userSearchApiUrl = auth0.baseUrl + '/users-by-email'; - - request({ - url: userSearchApiUrl, - headers: { - Authorization: 'Bearer ' + auth0.accessToken - }, - qs: { - email: user.email - } - }, - function(err, response, body) { - if (err) return callback(err); - if (response.statusCode !== 200) return callback(new Error(body)); - - var data = JSON.parse(body); - // Ignore non-verified users and current user, if present - data = data.filter(function(u) { - return u.email_verified && (u.user_id !== user.user_id); - }); - - if (data.length > 1) { - return callback(new Error('[!] Rule: Multiple user profiles already exist - cannot select base profile to link with')); - } - if (data.length === 0) { - console.log('[-] Skipping link rule'); - return callback(null, user, context); - } - - const originalUser = data[0]; - const provider = user.identities[0].provider; - const providerUserId = user.identities[0].user_id; - - request.post({ - url: userApiUrl + '/' + originalUser.user_id + '/identities', - headers: { - Authorization: 'Bearer ' + auth0.accessToken - }, - json: { - provider: provider, - user_id: String(providerUserId) - } - }, function(err, response, body) { - if (response.statusCode >= 400) { - return callback(new Error('Error linking account: ' + response.statusMessage)); - } - context.primaryUser = originalUser.user_id; - callback(null, user, context); - }); - }); -} diff --git a/test/rules/link-users-by-email-with-metadata.test.js b/test/rules/link-users-by-email-with-metadata.test.js deleted file mode 100644 index 5a74a896..00000000 --- a/test/rules/link-users-by-email-with-metadata.test.js +++ /dev/null @@ -1,229 +0,0 @@ -'use strict'; - -const nock = require('nock'); - -const loadRule = require('../utils/load-rule'); -const ContextBuilder = require('../utils/contextBuilder'); -const RequestBuilder = require('../utils/requestBuilder'); - -const ruleName = 'link-users-by-email-with-metadata'; - -describe(ruleName, () => { - let context; - let rule; - const auth0 = { - baseUrl: 'https://test.auth0.com', - accessToken: 'access_token', - users: { - updateAppMetadata: (id, metadata) => { - expect(id).toEqual('uid2'); - expect(metadata.test).toEqual('app-ok'); - return Promise.resolve(); - }, - updateUserMetadata: (id, metadata) => { - expect(id).toEqual('uid2'); - expect(metadata.test).toEqual('user-ok'); - return Promise.resolve(); - } - } - }; - - beforeEach(() => { - rule = loadRule(ruleName, { auth0 }); - }); - - describe('should do nothing', () => { - beforeEach(() => { - const request = new RequestBuilder().build(); - context = new ContextBuilder() - .withRequest(request) - .build(); - }); - - it('if no email data provided', (done) => { - rule({}, context, (err, u, c) => { - expect(err).toBeFalsy(); - done(); - }); - }); - - it('if no email isn`t verified', (done) => { - rule({ email: 'duck.t@example.com', email_verified: false }, context, (err, u, c) => { - expect(err).toBeFalsy(); - done(); - }); - }); - - it('if there is nothing to link', (done) => { - const user = { - user_id: 'uid1', - email: 'duck.t@example.com', - email_verified: true - }; - - nock('https://test.auth0.com') - .get('/users-by-email') - .query({ email: 'duck.t@example.com' }) - .reply(200, [ user ]); - - rule(user, context, (err, u, c) => { - expect(err).toBeFalsy(); - done(); - }); - }); - }); - - describe('should return error', () => { - beforeEach(() => { - const request = new RequestBuilder().build(); - context = new ContextBuilder() - .withRequest(request) - .build(); - }); - - it('if search call fails', (done) => { - const user = { - user_id: 'uid1', - email: 'duck.t@example.com', - email_verified: true - }; - - nock('https://test.auth0.com') - .get('/users-by-email') - .query({ email: 'duck.t@example.com' }) - .reply(400); - - rule(user, context, (err, u, c) => { - expect(err).toBeInstanceOf(Error); - done(); - }); - }); - - it('if there are too many users with same email', (done) => { - const user = { - user_id: 'uid1', - email: 'duck.t@example.com', - email_verified: true - }; - - const moreUsers = [ - { - user_id: 'uid2', - email: 'duck.t@example.com', - email_verified: true - }, - { - user_id: 'uid3', - email: 'duck.t@example.com', - email_verified: true - } - ]; - - nock('https://test.auth0.com') - .get('/users-by-email') - .query({ email: 'duck.t@example.com' }) - .reply(200, moreUsers); - - rule(user, context, (err, u, c) => { - expect(err).toBeInstanceOf(Error); - expect(err.message).toEqual('[!] Rule: Multiple user profiles already exist - cannot select base profile to link with'); - done(); - }); - }); - - it('if update call fails', (done) => { - const user = { - user_id: 'uid1', - email: 'duck.t@example.com', - email_verified: true, - identities: [ { - provider: 'auth0', - user_id: 'uid1' - } ], - app_metadata: { - test: 'app-ok' - }, - user_metadata: { - test: 'user-ok' - } - }; - - const moreUsers = [ - { - user_id: 'uid2', - email: 'duck.t@example.com', - email_verified: true - } - ]; - - nock('https://test.auth0.com') - .get('/users-by-email') - .query({ email: 'duck.t@example.com' }) - .reply(200, moreUsers); - - nock('https://test.auth0.com') - .post('/users/uid2/identities') - .reply(400); - - rule(user, context, (err, u, c) => { - expect(err).toBeInstanceOf(Error); - expect(err.message).toContain('Error linking account:'); - done(); - }); - }); - }); - - describe('should link users', () => { - beforeEach(() => { - const request = new RequestBuilder().build(); - context = new ContextBuilder() - .withRequest(request) - .build(); - }); - - it('if everything is ok', (done) => { - const user = { - user_id: 'uid1', - email: 'duck.t@example.com', - email_verified: true, - identities: [ { - provider: 'auth0', - user_id: 'uid1' - } ], - app_metadata: { - test: 'app-ok' - }, - user_metadata: { - test: 'user-ok' - } - }; - - const moreUsers = [ - { - user_id: 'uid2', - email: 'duck.t@example.com', - email_verified: true - } - ]; - - nock('https://test.auth0.com', { reqheaders: { 'Authorization': 'Bearer access_token' } }) - .get('/users-by-email') - .query({ email: 'duck.t@example.com' }) - .reply(200, moreUsers); - - nock('https://test.auth0.com', { reqheaders: { 'Authorization': 'Bearer access_token' } }) - .post('/users/uid2/identities', function(body) { - expect(body.provider).toEqual('auth0'); - expect(body.user_id).toEqual('uid1'); - return true; - }) - .reply(200); - - rule(user, context, (err, u, c) => { - expect(err).toBeFalsy(); - expect(c.primaryUser).toEqual('uid2'); - done(); - }); - }); - }); -}); diff --git a/test/rules/link-users-by-email.test.js b/test/rules/link-users-by-email.test.js deleted file mode 100644 index 937ac952..00000000 --- a/test/rules/link-users-by-email.test.js +++ /dev/null @@ -1,205 +0,0 @@ -'use strict'; - -const nock = require('nock'); - -const loadRule = require('../utils/load-rule'); -const ContextBuilder = require('../utils/contextBuilder'); -const RequestBuilder = require('../utils/requestBuilder'); - -const ruleName = 'link-users-by-email'; - -describe(ruleName, () => { - let context; - let rule; - const auth0 = { - baseUrl: 'https://test.auth0.com', - accessToken: 'access_token' - }; - - beforeEach(() => { - rule = loadRule(ruleName, { auth0 }); - }); - - describe('should do nothing', () => { - beforeEach(() => { - const request = new RequestBuilder().build(); - context = new ContextBuilder() - .withRequest(request) - .build(); - }); - - it('if no email data provided', (done) => { - rule({}, context, (err, u, c) => { - expect(err).toBeFalsy(); - done(); - }); - }); - - it('if no email isn`t verified', (done) => { - rule({ email: 'duck.t@example.com', email_verified: false }, context, (err, u, c) => { - expect(err).toBeFalsy(); - done(); - }); - }); - - it('if there is nothing to link', (done) => { - const user = { - user_id: 'uid1', - email: 'duck.t@example.com', - email_verified: true - }; - - nock('https://test.auth0.com') - .get('/users-by-email') - .query({ email: 'duck.t@example.com' }) - .reply(200, [ user ]); - - rule(user, context, (err, u, c) => { - expect(err).toBeFalsy(); - done(); - }); - }); - }); - - describe('should return error', () => { - beforeEach(() => { - const request = new RequestBuilder().build(); - context = new ContextBuilder() - .withRequest(request) - .build(); - }); - - it('if search call fails', (done) => { - const user = { - user_id: 'uid1', - email: 'duck.t@example.com', - email_verified: true - }; - - nock('https://test.auth0.com') - .get('/users-by-email') - .query({ email: 'duck.t@example.com' }) - .reply(400); - - rule(user, context, (err, u, c) => { - expect(err).toBeInstanceOf(Error); - done(); - }); - }); - - it('if there are too many users with same email', (done) => { - const user = { - user_id: 'uid1', - email: 'duck.t@example.com', - email_verified: true - }; - - const moreUsers = [ - { - user_id: 'uid2', - email: 'duck.t@example.com', - email_verified: true - }, - { - user_id: 'uid3', - email: 'duck.t@example.com', - email_verified: true - } - ]; - - nock('https://test.auth0.com') - .get('/users-by-email') - .query({ email: 'duck.t@example.com' }) - .reply(200, moreUsers); - - rule(user, context, (err, u, c) => { - expect(err).toBeInstanceOf(Error); - expect(err.message).toEqual('[!] Rule: Multiple user profiles already exist - cannot select base profile to link with'); - done(); - }); - }); - - it('if update call fails', (done) => { - const user = { - user_id: 'uid1', - email: 'duck.t@example.com', - email_verified: true, - identities: [ { - provider: 'auth0', - user_id: 'uid1' - } ] - }; - - const moreUsers = [ - { - user_id: 'uid2', - email: 'duck.t@example.com', - email_verified: true - } - ]; - - nock('https://test.auth0.com') - .get('/users-by-email') - .query({ email: 'duck.t@example.com' }) - .reply(200, moreUsers); - - nock('https://test.auth0.com') - .post('/users/uid2/identities') - .reply(400); - - rule(user, context, (err, u, c) => { - expect(err).toBeInstanceOf(Error); - expect(err.message).toContain('Error linking account:'); - done(); - }); - }); - }); - - describe('should link users', () => { - beforeEach(() => { - const request = new RequestBuilder().build(); - context = new ContextBuilder() - .withRequest(request) - .build(); - }); - - it('if everything is ok', (done) => { - const user = { - user_id: 'uid1', - email: 'duck.t@example.com', - email_verified: true, - identities: [ { - provider: 'auth0', - user_id: 'uid1' - } ] - }; - - const moreUsers = [ - { - user_id: 'uid2', - email: 'duck.t@example.com', - email_verified: true - } - ]; - - nock('https://test.auth0.com', { reqheaders: { 'Authorization': 'Bearer access_token' } }) - .get('/users-by-email') - .query({ email: 'duck.t@example.com' }) - .reply(200, moreUsers); - - nock('https://test.auth0.com', { reqheaders: { 'Authorization': 'Bearer access_token' } }) - .post('/users/uid2/identities', function(body) { - expect(body.provider).toEqual('auth0'); - expect(body.user_id).toEqual('uid1'); - return true; - }) - .reply(200); - - rule(user, context, (err, u, c) => { - expect(err).toBeFalsy(); - expect(c.primaryUser).toEqual('uid2'); - done(); - }); - }); - }); -});