Skip to content

Commit

Permalink
feat: Update LinkedIn to use new lite profile (#391)
Browse files Browse the repository at this point in the history
### Changes
 - Switched to use the new `liteprofile` scope
 - Grabs email from new dedicated endpoint

Fixes #390
  • Loading branch information
dawnerd authored and AdriVanHoudt committed Mar 5, 2019
1 parent 5c28ac3 commit 8005df9
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 32 deletions.
30 changes: 13 additions & 17 deletions lib/providers/linkedin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

// Load modules

const Crypto = require('crypto');


// Declare internals

Expand All @@ -15,33 +13,31 @@ exports = module.exports = function (options) {
return {
protocol: 'oauth2',
useParamsAuth: true,
auth: 'https://www.linkedin.com/uas/oauth2/authorization',
token: 'https://www.linkedin.com/uas/oauth2/accessToken',
scope: ['r_basicprofile', 'r_emailaddress'],
auth: 'https://www.linkedin.com/oauth/v2/authorization',
token: 'https://www.linkedin.com/oauth/v2/accessToken',
scope: ['r_liteprofile', 'r_emailaddress'],
scopeSeparator: ',',
profile: async function (credentials, params, get) {

const query = {
format: 'json',
appsecret_proof: Crypto.createHmac('sha256', this.clientSecret).update(credentials.token).digest('hex')
};

let fields = '';
if (this.providerParams && this.providerParams.fields) {
fields = this.providerParams.fields;
fields = '?projection=' + this.providerParams.fields;
}

const profile = await get('https://api.linkedin.com/v1/people/~' + fields, query);
const profile = await get('https://api.linkedin.com/v2/me' + fields);
const email = await get('https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))');

credentials.profile = {
id: profile.id,
name: {
first: profile.firstName,
last: profile.lastName
first: profile.firstName.localized[Object.keys(profile.firstName.localized)[0]],
last: profile.lastName.localized[Object.keys(profile.lastName.localized)[0]]
},
email: profile.emailAddress,
headline: profile.headline,
raw: profile
email: email.elements[0]['handle~'].emailAddress,
raw: {
profile,
email
}
};
}
};
Expand Down
7 changes: 6 additions & 1 deletion test/mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,12 @@ exports.override = function (uri, payload) {

if (dest.indexOf(uri) === 0) {
if (typeof payload === 'function') {
await payload(dest);
const res = await payload(dest);

if (res) {
return { res: { statusCode: 200 }, payload: JSON.stringify(res) };
}

team.attend();
return { res: { statusCode: 200 }, payload: '{"x":1}' };
}
Expand Down
99 changes: 85 additions & 14 deletions test/providers/linkedin.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,43 @@ describe('linkedin', () => {

const profile = {
id: '1234567890',
firstName: 'steve',
lastName: 'smith',
emailAddress: 'steve.smith@domain.com',
headline: 'Master of the universe'
firstName: {
localized: {
en_US: 'steve'
},
preferredLocal: {
country: 'US',
language: 'en'
}
},
lastName: {
localized: {
en_US: 'smith'
},
preferredLocal: {
country: 'US',
language: 'en'
}
}
};

const email = {
elements: [{
handle: 'urn:li:emailAddress:3775708763',
'handle~': {
emailAddress: 'steve.smith@domain.com'
}
}]
};

Mock.override('https://api.linkedin.com/v1/people/~', profile);
Mock.override('https://api.linkedin.com/v2', (dest) => {

if (dest.startsWith('https://api.linkedin.com/v2/me')) {
return profile;
}

return email;
});

server.auth.strategy('custom', 'bell', {
password: 'cookie_encryption_password_secure',
Expand Down Expand Up @@ -76,8 +106,10 @@ describe('linkedin', () => {
last: 'smith'
},
email: 'steve.smith@domain.com',
headline: 'Master of the universe',
raw: profile
raw: {
profile,
email
}
}
});
});
Expand All @@ -97,25 +129,64 @@ describe('linkedin', () => {

const profile = {
id: '1234567890',
firstName: 'steve',
lastName: 'smith',
headline: 'Master of the universe'
firstName: {
localized: {
en_US: 'steve'
},
preferredLocal: {
country: 'US',
language: 'en'
}
},
lastName: {
localized: {
en_US: 'smith'
},
preferredLocal: {
country: 'US',
language: 'en'
}
}
};

const email = {
elements: [{
handle: 'urn:li:emailAddress:3775708763',
'handle~': {
emailAddress: 'steve.smith@domain.com'
}
}]
};

let profileChecked = false;

const get = (url, query) => {

expect(url).to.equal('https://api.linkedin.com/v1/people/~(id,firstName)');
return profile;
if (!profileChecked) {
expect(url).to.equal('https://api.linkedin.com/v2/me?projection=(id,firstName)');
profileChecked = true;
return profile;
}

expect(url).to.equal('https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))');

return email;
};

await custom.profile({ token: '456' }, null, get);

delete custom.providerParams.fields;
profileChecked = false;

const get2 = (url, query) => {

expect(url).to.equal('https://api.linkedin.com/v1/people/~');
return profile;
if (!profileChecked) {
expect(url).to.equal('https://api.linkedin.com/v2/me');
profileChecked = true;
return profile;
}

return email;
};

await custom.profile({ token: '456' }, null, get2);
Expand Down

0 comments on commit 8005df9

Please sign in to comment.