From 5c3867f47793119e5a54fcb25c415cf34804d6c9 Mon Sep 17 00:00:00 2001 From: Juan Pablo Mejia Date: Wed, 22 Dec 2021 22:09:09 -0500 Subject: [PATCH 1/2] feat(server): Migrate getTokenResponse from http to fetch --- linkedin-server.js | 70 ++++++++++++++++++++-------------------------- package.js | 1 + 2 files changed, 32 insertions(+), 39 deletions(-) diff --git a/linkedin-server.js b/linkedin-server.js index f619c98..1edc7ba 100644 --- a/linkedin-server.js +++ b/linkedin-server.js @@ -40,51 +40,42 @@ const isJSON = (str) => { } }; -// returns an object containing: -// - accessToken -// - expiresIn: lifetime of token in seconds -const getTokenResponse = (query) => { +// returns an object containing: accessToken, expiresIn (lifetime of token in seconds) +const getTokenResponse = async (query, callback) => { const config = ServiceConfiguration.configurations.findOne({ service: 'linkedin' }); if (!config) { throw new ServiceConfiguration.ConfigError(); } - let responseContent; - - try { - // Request an access token - responseContent = HTTP.get('https://api.linkedin.com/uas/oauth2/accessToken', { - params: { - grant_type: 'authorization_code', - client_id: config.clientId, - client_secret: OAuth.openSecret(config.secret), - code: query.code, - redirect_uri: OAuth._redirectUri('linkedin', config) - } - }).content; - } catch (err) { - throw new Error(`Failed to complete OAuth handshake with Linkedin. ${err.message}`); + const content = new URLSearchParams({ + grant_type: 'authorization_code', + client_id: config.clientId, + client_secret: OAuth.openSecret(config.secret), + code: query.code, + redirect_uri: OAuth._redirectUri('linkedin', config) + }); + + const request = await fetch('https://api.linkedin.com/uas/oauth2/accessToken', { + method: 'POST', + headers: { Accept: 'application/json' }, + body: content + }); + + const response = await request.json(); + + if (response.error) { + callback(response.error); + throw new Error(`Failed to complete OAuth handshake with Linkedin. ${response.error}`); + } else { + const data = { + accessToken: response.access_token, + expiresIn: response.expires_in + }; + + callback(undefined, data); + return data; } - - // If 'responseContent' does not parse as JSON, it is an error. - if (!isJSON(responseContent)) { - throw new Error(`Failed to complete OAuth handshake with Linkedin. ${responseContent}`); - } - - // Success! Extract access token and expiration - const parsedResponse = JSON.parse(responseContent); - const accessToken = parsedResponse.access_token; - const expiresIn = parsedResponse.expires_in; - - if (!accessToken) { - throw new Error(`Failed to complete OAuth handshake with Linkedin -- can't find access token in HTTP response. ${responseContent}`); - } - - return { - accessToken, - expiresIn - }; }; // Request available fields from r_liteprofile @@ -98,7 +89,8 @@ const getIdentity = (accessToken) => { }; OAuth.registerService('linkedin', 2, null, query => { - const response = getTokenResponse(query); + const responseCall = Meteor.wrapAsync(getTokenResponse); + const response = responseCall(query); const { accessToken } = response; const identity = getIdentity(accessToken); diff --git a/package.js b/package.js index 2187742..069eb2f 100644 --- a/package.js +++ b/package.js @@ -11,6 +11,7 @@ Package.onUse(function(api) { api.use('ecmascript'); api.use('oauth2', ['client', 'server']); api.use('oauth', ['client', 'server']); + api.use('fetch', 'server'); api.use('http@1.4.4 || 2.0.0', 'server'); api.use('random', 'client'); api.use('service-configuration', ['client', 'server']); From 36ed198f32790ec0e3dd08fe5b07f478d03c7c83 Mon Sep 17 00:00:00 2001 From: Juan Pablo Mejia Date: Mon, 27 Dec 2021 13:36:16 -0500 Subject: [PATCH 2/2] feat(server): remove unused isJSON function --- linkedin-server.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/linkedin-server.js b/linkedin-server.js index 1edc7ba..3e351af 100644 --- a/linkedin-server.js +++ b/linkedin-server.js @@ -30,16 +30,6 @@ const getEmails = (accessToken) => { return emails; }; -// checks whether a string parses as JSON -const isJSON = (str) => { - try { - JSON.parse(str); - return true; - } catch (err) { - return false; - } -}; - // returns an object containing: accessToken, expiresIn (lifetime of token in seconds) const getTokenResponse = async (query, callback) => { const config = ServiceConfiguration.configurations.findOne({ service: 'linkedin' });