diff --git a/packages/nodes-base/credentials/LinkedInCommunityManagementOAuth2Api.credentials.ts b/packages/nodes-base/credentials/LinkedInCommunityManagementOAuth2Api.credentials.ts
new file mode 100644
index 0000000000000..1c64bcfe1a733
--- /dev/null
+++ b/packages/nodes-base/credentials/LinkedInCommunityManagementOAuth2Api.credentials.ts
@@ -0,0 +1,54 @@
+import type { ICredentialType, INodeProperties } from 'n8n-workflow';
+
+const scopes = ['w_member_social', 'w_organization_social', 'r_basicprofile'];
+
+export class LinkedInCommunityManagementOAuth2Api implements ICredentialType {
+ name = 'linkedInCommunityManagementOAuth2Api';
+
+ extends = ['oAuth2Api'];
+
+ displayName = 'LinkedIn Community Management OAuth2 API';
+
+ documentationUrl = 'linkedIn';
+
+ properties: INodeProperties[] = [
+ {
+ displayName: 'Grant Type',
+ name: 'grantType',
+ type: 'hidden',
+ default: 'authorizationCode',
+ },
+ {
+ displayName: 'Authorization URL',
+ name: 'authUrl',
+ type: 'hidden',
+ default: 'https://www.linkedin.com/oauth/v2/authorization',
+ required: true,
+ },
+ {
+ displayName: 'Access Token URL',
+ name: 'accessTokenUrl',
+ type: 'hidden',
+ default: 'https://www.linkedin.com/oauth/v2/accessToken',
+ required: true,
+ },
+ {
+ displayName: 'Scope',
+ name: 'scope',
+ type: 'hidden',
+ default: scopes.join(' '),
+ },
+ {
+ displayName: 'Auth URI Query Parameters',
+ name: 'authQueryParameters',
+ type: 'hidden',
+ default: '',
+ },
+ {
+ displayName: 'Authentication',
+ name: 'authentication',
+ type: 'hidden',
+ default: 'body',
+ },
+ ];
+}
diff --git a/packages/nodes-base/credentials/LinkedInOAuth2Api.credentials.ts b/packages/nodes-base/credentials/LinkedInOAuth2Api.credentials.ts
index 065115a69822b..6f186fabd82a0 100644
--- a/packages/nodes-base/credentials/LinkedInOAuth2Api.credentials.ts
+++ b/packages/nodes-base/credentials/LinkedInOAuth2Api.credentials.ts
@@ -42,7 +42,7 @@ export class LinkedInOAuth2Api implements ICredentialType {
name: 'scope',
type: 'hidden',
default:
- '=w_member_social{{$self["organizationSupport"] === true ? ",w_organization_social":",r_liteprofile,r_emailaddress"}}',
+ '=w_member_social{{$self["organizationSupport"] === true ? ",w_organization_social": $self["legacy"] === true ? ",r_liteprofile,r_emailaddress" : ",profile,email,openid"}}',
description:
'Standard scopes for posting on behalf of a user or organization. See this resource .',
},
@@ -58,5 +58,12 @@ export class LinkedInOAuth2Api implements ICredentialType {
type: 'hidden',
default: 'body',
},
+ {
+ displayName: 'Legacy',
+ name: 'legacy',
+ type: 'boolean',
+ default: true,
+ description: 'Whether to use the legacy API',
+ },
];
}
diff --git a/packages/nodes-base/nodes/LinkedIn/GenericFunctions.ts b/packages/nodes-base/nodes/LinkedIn/GenericFunctions.ts
index 093356a14ba1f..160780d18deb5 100644
--- a/packages/nodes-base/nodes/LinkedIn/GenericFunctions.ts
+++ b/packages/nodes-base/nodes/LinkedIn/GenericFunctions.ts
@@ -25,6 +25,14 @@ export async function linkedInApiRequest(
binary?: boolean,
_headers?: object,
): Promise {
+ const authenticationMethod = this.getNodeParameter('authentication', 0);
+ const credentialType =
+ authenticationMethod === 'standard'
+ ? 'linkedInOAuth2Api'
+ : 'linkedInCommunityManagementOAuth2Api';
+
+ const baseUrl = 'https://api.linkedin.com';
+
let options: OptionsWithUrl = {
headers: {
Accept: 'application/json',
@@ -33,9 +41,10 @@ export async function linkedInApiRequest(
},
method,
body,
- url: binary ? endpoint : `https://api.linkedin.com/rest${endpoint}`,
+ url: binary ? endpoint : `${baseUrl}${endpoint.includes('v2') ? '' : '/rest'}${endpoint}`,
json: true,
};
+
options = Object.assign({}, options, {
resolveWithFullResponse: true,
});
@@ -51,7 +60,7 @@ export async function linkedInApiRequest(
try {
return resolveHeaderData(
- await this.helpers.requestOAuth2.call(this, 'linkedInOAuth2Api', options, {
+ await this.helpers.requestOAuth2.call(this, credentialType, options, {
tokenType: 'Bearer',
}),
);
diff --git a/packages/nodes-base/nodes/LinkedIn/LinkedIn.node.ts b/packages/nodes-base/nodes/LinkedIn/LinkedIn.node.ts
index 4f95de5c7da71..c341efe2d599b 100644
--- a/packages/nodes-base/nodes/LinkedIn/LinkedIn.node.ts
+++ b/packages/nodes-base/nodes/LinkedIn/LinkedIn.node.ts
@@ -28,9 +28,39 @@ export class LinkedIn implements INodeType {
{
name: 'linkedInOAuth2Api',
required: true,
+ displayOptions: {
+ show: {
+ authentication: ['standard'],
+ },
+ },
+ },
+ {
+ name: 'linkedInCommunityManagementOAuth2Api',
+ required: true,
+ displayOptions: {
+ show: {
+ authentication: ['communityManagement'],
+ },
+ },
},
],
properties: [
+ {
+ displayName: 'Authentication',
+ name: 'authentication',
+ type: 'options',
+ options: [
+ {
+ name: 'Standard',
+ value: 'standard',
+ },
+ {
+ name: 'Community Management',
+ value: 'communityManagement',
+ },
+ ],
+ default: 'standard',
+ },
{
displayName: 'Resource',
name: 'resource',
@@ -55,12 +85,24 @@ export class LinkedIn implements INodeType {
// Get Person URN which has to be used with other LinkedIn API Requests
// https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin
async getPersonUrn(this: ILoadOptionsFunctions): Promise {
- const returnData: INodePropertyOptions[] = [];
- const person = await linkedInApiRequest.call(this, 'GET', '/me', {});
- returnData.push({
- name: `${person.localizedFirstName} ${person.localizedLastName}`,
- value: person.id,
- });
+ const authentication = this.getNodeParameter('authentication', 0);
+ let endpoint = '/me';
+ if (authentication === 'standard') {
+ const { legacy } = await this.getCredentials('linkedInOAuth2Api');
+ if (!legacy) {
+ endpoint = '/v2/userinfo';
+ }
+ }
+ const person = await linkedInApiRequest.call(this, 'GET', endpoint, {});
+ const firstName = person.localizedFirstName ?? person.given_name;
+ const lastName = person.localizedLastName ?? person.family_name;
+ const name = `${firstName} ${lastName}`;
+ const returnData: INodePropertyOptions[] = [
+ {
+ name,
+ value: person.id ?? person.sub,
+ },
+ ];
return returnData;
},
},
diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json
index 63ecf0f7359b2..34732e3cd4b90 100644
--- a/packages/nodes-base/package.json
+++ b/packages/nodes-base/package.json
@@ -195,6 +195,7 @@
"dist/credentials/LinearOAuth2Api.credentials.js",
"dist/credentials/LineNotifyOAuth2Api.credentials.js",
"dist/credentials/LingvaNexApi.credentials.js",
+ "dist/credentials/LinkedInCommunityManagementOAuth2Api.credentials.js",
"dist/credentials/LinkedInOAuth2Api.credentials.js",
"dist/credentials/LoneScaleApi.credentials.js",
"dist/credentials/Magento2Api.credentials.js",