Cannot authorize with LinkedIn - javascript

I'm trying to get the first name, surname and email from a user on my website with LinkedIn. This is what I've done:
In my LinkedIn App I've set the Default Scope (OAuth User Agreement) to:
r_basicprofile
r_contactinfo
w_share
r_emailaddress
I've correctly added my domain to Javascript API Domains. I didn't add a link to OAuth 2.0 Redirect URLs. But I don't know if that's mandatory (and which path to insert)?
I've also copied my API Key (Consumer Key).
Now in my HTML I have:
<script type="text/javascript" src="http://platform.linkedin.com/in.js">
lang: en_US
api_key: myapikey
scope: r_basicprofile r_emailaddress
</script>
<input class="apply-with-linkedin" type="button" value="Apply with LinkedIn" id="btn-linkedin-apply">
<script type="text/javascript">
jQuery('#btn-linkedin-apply').click(function (e) {
e.preventDefault();
e.stopPropagation();
IN.User.authorize(function ()
{
IN.API.Profile('me').fields([
'firstName',
'lastName',
'emailAddress'
]).result(function (profiles)
{
var me = profiles.values[0];
if (me.hasOwnProperty('firstName')) {
jQuery('#apply-form #input-firstname').val(me.firstName);
}
if (me.hasOwnProperty('lastName')) {
jQuery('#apply-form #input-lastname').val(me.lastName);
}
if (me.hasOwnProperty('emailAddress')) {
jQuery('#apply-form #input-email').val(me.emailAddress);
}
});
});
});
</script>
But I always get the javascript error Cannot read property 'authorize' of undefined when I click the button. The IN.User is undefined.
What could be wrong with this? ...
UPDATE:
The javascript code where I specify my API Key, ... I've copied from the "Getting Started with the JavaScript SDK" from LinkedIn.
<script type="text/javascript" src="//platform.linkedin.com/in.js">
api_key: [API_KEY]
onLoad: [ONLOAD]
authorize: [AUTHORIZE]
lang: [LANG_LOCALE]
</script>

It seems likely that you are just experiencing problems with the asynchronicity of the library. I've modified the sample code from the Sign in with LinkedIn Javascript example slightly for you, but I think your issue will be solved with paying more attention to the callbacks so that you know a) the library is loaded, and b) the API call has successfully completed - before attempting to access any of the resulting data:
<script type="text/javascript" src="//platform.linkedin.com/in.js">
api_key: YOUR_API_KEY_HERE
authorize: true
scope: r_basicprofile r_emailaddress
onLoad: onLinkedInLoad
</script>
<script type="text/javascript">
// Setup an event listener to make an API call once auth is complete
function onLinkedInLoad() {
IN.Event.on(IN, "auth", getProfileData);
}
// Handle the successful return from the API call
function onSuccess(data) {
// Pre-populate your form fields here once you know the call
// came back successfully
}
// Handle an error response from the API call
function onError(error) {
console.log(error);
}
// Use the API call wrapper to request the member's basic profile data
function getProfileData() {
IN.API.Raw("/people/~:(firstName,lastName,emailAddress)").result(onSuccess).error(onError);
}
</script>

Related

Google's JS tutorial for Analytics Reporting API v4 fails due to outdated oauth library

I've set up API access for my (Universal) Analytics project and it works fine from Google's "Demos and Tools" via Request Composer. So then I picked up the simple tutorial HTML file from here:
https://developers.google.com/analytics/devguides/reporting/core/v4/quickstart/web-js
But as soon as the page loads, there's an error in the console saying: You have created a new client application that uses libraries for user authentication or authorization that will soon be deprecated... etc etc.
But the library doesn't seem to have been deprecated yet (this seems to be coming in March 2023).
Anyway, I attempted to keep in pace with the times and use the new library, following the guide here:
https://developers.google.com/identity/gsi/web/guides/migration#popup-mode_1
That led nowhere (403 errors and other problems, as it seems that is not suited for API access). Eventually, though, I found a guide that shows how to use GIS for accessing an API:
https://developers.google.com/identity/oauth2/web/guides/migration-to-gis
Using this, I managed to cobble up together a working query. I'll post it as the answer. This is to help others that are affected by the outdated tutorial.
Enable the Analytics API in the way indicated by this tutorial: https://www.jcchouinard.com/google-api/
You'll want to create credentials for an Internal Web Application, and set "Authorized JavaScript origins" to http://localhost:8080
Save this as .html and serve it on localhost:8080. It should ask you to sign in, you should see the name of your Web Application in the Sign In prompt. And once you press on "Query Reports" you should get a nice JSON back.
<!DOCTYPE html>
<html>
<head>
<script src="https://apis.google.com/js/client:platform.js"></script>
<script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
</head>
<body>
<script>
var client;
var access_token;
function initClient() {
client = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR-CLIENT-ID',
scope: 'https://www.googleapis.com/auth/analytics.readonly',
callback: (tokenResponse) => {
access_token = tokenResponse.access_token;
},
});
}
function getToken() {
client.requestAccessToken();
}
function revokeToken() {
google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});
}
function loadCalendar() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
xhr.send();
}
</script>
<script>
// Replace with your view ID.
var VIEW_ID = 'YOUR-VIEW-ID';
// Query the API and print the results to the page.
function queryReports() {
gapi.client.request({
path: '/v4/reports:batchGet',
root: 'https://analyticsreporting.googleapis.com/',
method: 'POST',
body: {
reportRequests: [
{
viewId: VIEW_ID,
dateRanges: [
{
startDate: '7daysAgo',
endDate: 'today'
}
],
metrics: [
{
expression: 'ga:sessions'
}
]
}
]
}
}).then(displayResults, console.error.bind(console));
}
function displayResults(response) {
var formattedJson = JSON.stringify(response.result, null, 2);
document.getElementById('query-output').value = formattedJson;
}
</script>
<h1>Google Identity Services Authorization Token model</h1>
<button onclick="getToken();">Get access token</button><br><br>
<button onclick="queryReports();">Query Reports</button><br><br>
<button onclick="revokeToken();">Revoke token</button>
<!-- The API response will be printed here. -->
<textarea cols="80" rows="20" id="query-output"></textarea>
</body>
</html>

ADAL.js - acquire token for Graph API resources

I'm developing a SPA app in React that needs to integrate with AzureAD and the GraphAPI (implicit flow).
My question is very similar to: ADAL.js - Obtaining Microsoft Graph Access Token with id_token ... but the answer doesn't show me enough code to get me on my way.
So far, using just adal.js (v1.0.14), I can login & get an id_token, but I can't figure out how to use it to get access to make Graph API calls.
UPDATE: I know I'm correctly registered with the Azure portal, because I was able to login and get recent docs without adal.js or any lib ... just using home-made ajax calls.
Here's my code, which does the login/redirect, and then tries to get my recent docs:
// Initial setup
var adalCfg = {
instance : 'https://login.microsoftonline.com/',
tenant : 'common',
clientId : 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
postLogoutRedirectUri : window.location.origin,
extraQueryParameter : 'scope=Mail.ReadWrite+Files.Read+Files.ReadWrite+User.ReadBasic.All' // Is this the proper way to specify what resources I need access to?
};
var authContext = new Adal(adalCfg);
if(!authContext.getCachedUser()) {
authContext.login(); // redirects MS login page successfully
}
// Check For & Handle Redirect From AAD After Login
var isCallback = authContext.isCallback(window.location.hash); // Checks if the URL fragment contains access token, id token or error_description.
if(isCallback) {
authContext.handleWindowCallback(); // extracts the hash, processes the token or error, saves it in the cache and calls the registered callbacks with the result.
}
if (isCallback && !authContext.getLoginError()) {
window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST); // redirects back to /
}
// Try to get my recent docs - FAILS with InvalidAuthenticationToken error
// UDPATED authContext.acquireToken(authContext.config.clientId, function (error, token) {
authContext.acquireToken('https://graph.microsoft.com', function (error, token) {
$.ajax({
url: 'https://graph.microsoft.com/v1.0/me/drive/recent',
headers:{'authorization':'Bearer '+ token},
type:'GET',
dataType:'json'
}).done(function(res) {
console.log(res['value']);
});
});
What have I got wrong?
Update 2: I changed acquireToken per Fei's answer, but now when adal silently gets an access token for my resource, it fails to pass it to my API call.
Updated code:
adalCfg.endpoints.graphApiUri = "https://graph.microsoft.com";
authContext.acquireToken(adalCfg.endpoints.graphApiUri, function (errorDesc, token, error) {
console.log('errorDesc = ' + errorDesc)
console.log('token = ' + token)
console.log('error = ' + error)
$.ajax({
url: adalCfg.endpoints.graphApiUri + '/v1.0/me/drive/recent',
headers:{'authorization':'Bearer '+ token},
type:'GET',
dataType:'json'
}).done(function(res) {
console.log(res['value']);
});
});
And console output:
Token not being captured
The image shows the req for a token, which appears to succeed, because the next GET contains the access_token in the hash. However, acquireToken passes a null token to my Graph API call.
However, if I manually grab the access token out of the hash, I can successfully make the Graph API call.
Why doesn't adal pass the access token to my API call? It came back and is valid.
To call the Microsoft Graph, we need to get the specific token for this resource. Based on the code you were acquire the token using the authContext.config.clientId.
If you register the app on Azure portal, to get the access token for the Microsoft Graph, you need to replace authContext.config.clientId with https://graph.microsoft.com.
And to call the REST sucessfully, we need to make sure having the enough permission. For example, to list recent files, one of the following scopes is required:Files.Read,Files.ReadWrite,Files.Read.All,Files.ReadWrite.All,Sites.Read.All,Sites.ReadWrite.All(refer here).
Update
<html>
<head>
<script src="\node_modules\jquery\dist\jquery.js"></script>
<script src="node_modules\adal-angular\lib\adal.js"></script>
</head>
<body>
<button id="login"> login</button>
<button id="clickMe">click me</button>
<script>
$(function () {
var endpoints = {
"https://graph.microsoft.com": "https://graph.microsoft.com"
};
window.config = {
tenant: 'xxxx.onmicrosoft.com',
clientId: 'xxxxxxxxxxxxxxxxx',
endpoints: endpoints
};
window.authContext = new AuthenticationContext(config);
$("#login").click(function () {
window.authContext.login();
});
$("#clickMe").click(function () {
var user = window.authContext.getCachedUser();
console.log(user);
window.authContext.acquireToken('https://graph.microsoft.com', function (error, token) {
console.log(error);
console.log(token);
$.ajax({
url: 'https://graph.microsoft.com/v1.0/me/',
headers:{'authorization':'Bearer '+ token},
type:'GET',
dataType:'json'
}).done(function(res) {
console.log(res['userPrincipalName']);
});
});
}
);
function init(){
if(window.location.hash!="")
window.authContext.handleWindowCallback(window.location.hash);
}
init();
});
</script>
</body>
</html>

Soundcloud ajax response not reached

I'm executing this query to get an user in SoundCloud.
I can see that the call is correctly done in Chrome network tab, after a click, however, it doesn't reach the javascript alert. So I can't retrieve the JSON response and add it to the DOM.
<script src="https://connect.soundcloud.com/sdk/sdk-3.1.2.js"></script>
<script>
SC.initialize({
client_id: '067320efe29b7da263fd8bb093911116',
redirect_uri: 'trofeosbalbino.com/beonerecords'
});
$("#embedTrack").click(function() {
SC.get('/users', {q: 'beonerecords'}, function (users) {
alert(users);
});
});
</script>
When using the SoundCloud API in a client side web application, you should use the SC.connect() method to authenticate the application. Try something such as the following:
SC.initialize({
client_id: '067320efe29b7da263fd8bb093911116',
redirect_uri: 'http://trofeosbalbino.com/beonerecords'
});
$("#embedTrack").click(function() {
SC.connect().then(function(){
SC.get('/users', {q: 'beonerecords'}, function (users) {
return users;
});
}).then(function(users){
alert(users);
});
});

Parse JSON string values

I have a big problem, I hope somebody can help me solve. I am trying to make a Linkedin sharing function from the API. The content there is in the JSON is postet perfectly on LinkedIn. But the problem is that a person cannot see what there is posted in the posting box. I uploaded my share button to my domain, if somebody wants to test it:
http://www.vouzalis.com/wwwroot/stackTest.html
As I see it, I did everything the API ask:
https://developer.linkedin.com/docs/share-on-linkedin
I cannot see what else I am missing? Does anybody have a clue of what there could be wrong?
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript" src="http://platform.linkedin.com/in.js">
api_key: myAPIKey
authorize: true
onLoad: onLinkedInLoad
lang : da_DK
</script>
</head>
<body>
<script type="in/Share">
</script>
<script>
// Setup an event listener to make an API call once auth is complete
function onLinkedInLoad() {
IN.Event.on(IN, "auth", shareContent);
}
// Handle the successful return from the API call
function onSuccess(data) {
console.log(data);
}
// Handle an error response from the API call
function onError(error) {
console.log(error);
}
// Use the API call wrapper to share content on LinkedIn
function shareContent() {
// Build the JSON payload containing the content to be shared
var payload = {
"comment": "Check this awesome website out",
"content": {
"title": "Hello",
"description": "StackOverflow",
"submitted-url": "https://www.stackoverflow.com",
"submitted-image-url": "http://i.telegraph.co.uk/multimedia/archive/03597/POTD_chick_3597497k.jpg"
},
"visibility": {
"code": "anyone"
}
}
IN.API.Raw("/people/~/shares?format=json")
.method("POST")
.body(JSON.stringify(payload))
.result(onSuccess)
.error(onError);
};
</script>
</body>
</html>

Getting at LinkedIn returned data from Javascript SDK

What I'd like to do is get at the returned data from the LinkedIn API named data from the function named getProfileData. How can I access the data that contains the information such as firstName and lastName but in getProfileData and not just in the function onSuccess?
<script type="text/javascript" src="//platform.linkedin.com/in.js">
api_key: YOUR_API_KEY_HERE
authorize: true
onLoad: onLinkedInLoad
</script>
<script type="text/javascript">
// Setup an event listener to make an API call once auth is complete
function onLinkedInLoad() {
IN.Event.on(IN, "auth", getProfileData);
}
// Handle the successful return from the API call
function onSuccess(data) {
console.log(data);
}
// Handle an error response from the API call
function onError(error) {
console.log(error);
}
// Use the API call wrapper to request the member's basic profile data
function getProfileData() {
IN.API.Raw("/people/~").result(onSuccess).error(onError);
// I want to see the profile data in here.
}
</script>
You must fix something in your code :
IN.API.Raw("/people/~:(id,first-name,last-name,location,positions)?format=json").result(onSuccess).error(onError);

Categories