I'm working on website where users can add projects. They can add a link of their website to project. But to verify that website is their they must add some script and generated token to head of their website index.
I want to make something like this:
<script src="linktoscript" data-sitekey="token"></script>
But I don't know how to load that "token" at the script.
I tried:
var token = response('data-sitekey');
Didn't work.
Here is one solution, but there are many more.
I advise you not to have them add a script to thier site. They will probably not thrust your script and refuse to let it run on their website.
Also if your script on their site sends the token to your server you cannot verify that the request actually came from their website. They could have just as well run your script on their local machiene.
Step 1
Generate a token and store it in your DB together with the url of their website
Example token tJ0qEKJQlp2ZXb19
Step 2
Ask the user to add this meta tag to their site.
Assuming your website is called example.com
<meta name="example.com-token" content="tJ0qEKJQlp2ZXb19">
Step 3
Verify that the meta tag exists on their site.
In JS:
fetch(urlOfTheirSite, {
headers: {
"Content-Type": "text/html",
},
}).then((resp) => {
if(!resp.ok) {
//Cannot fetch thier website
}
resp.text()
}).then((html) => {
var doc = new DOMParser().parseFromString(stringContainingHTMLSource, "text/html");
var token = doc.querySelector("meta[name=example.com-token]");
/*
* Send token and url of the website to your server for verification.
* On your server check if the url and the token match the entry in your DB
*/
})
In PHP:
Use cURL and this RegEx
meta\s+name="?example\.com-token"?\s*content="?(\w+)"?\s*
The first capture group will contain the token
Step 4
Tell your user that their site has been verified and that they can remove the meta tag now.
Probably document.currentScript is what you are looking for. document.currentScript returns the DOM of <script>.
Try something like this:
console.log(document.currentScript.dataset.sitekey)
I hosted a demo. Use "View Source" to see the code.
Related
I am trying to add an app to our SharePoint Online site using the template from https://learn.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/get-started/build-a-hello-world-web-part and we get the error below when we deploy to SharePoint and add the app/Web part to a test SharePoint site. We are using TypeScript as the template uses.
Has anyone else encountered this issue or know where to look for the issue?
Found [object Object]Driver Display External Error: Error: AADSTS500011: The resource principal named https://driverdisplayexternal.azurewebsites.net was not found in the tenant named 7018324c-9efd-4880-809d-b2e6bb1606b6. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant. Trace ID: 358b22eb-cd2c-4091-b592-5a57cbc21d00 Correlation ID: ec96d656-1a36-42e2-a2b9-3ff78efc1e2e Timestamp: 2019-10-01 16:26:06Z
We have added a call to our own client as shown below. We are not sure why the resource principal was not found. The Tenant ID's match and things seem to be set up properly for authentication.
HelloWorldWebPart.ts
...
this.context.aadHttpClientFactory
.getClient('https://driverdisplayexternal.azurewebsites.net')
.then((client: AadHttpClient): void => {
client
.get('https://driverdisplayexternal.azurewebsites.net/api/values', AadHttpClient.configurations.v1)
.then((response: HttpClientResponse): Promise < Order[] > => {
this.domElement.innerHTML += 'Received a response from Driver Display External: ' + response;
return response.json();
})
.catch(error => {
this.domElement.innerHTML += 'Driver Display External Error: ' + error;
console.error(error);
});
});
...
package-solution.json
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": {
"name": "helloworld-webpart-client-side-solution",
"id": "**ID**",
"version": "4.1.0.0",
"includeClientSideAssets": true,
"isDomainIsolated": false,
"webApiPermissionRequests": [
{
"resource": "DriverDisplayExternal",
"scope": "User.Read.All"
}
]
},
"paths": {
"zippedPackage": "solution/helloworld-webpart.sppkg"
}
}
Any help or direction to where the issue may be would be very appreciated. Thanks in advance!
Never used this API, but if I had to guess you need to change the value here:
.getClient('https://driverdisplayexternal.azurewebsites.net')
You can use either the client id / application id, or the application ID URI.
Sometimes this problem can occurr when you set a wrong name for the scope you are requesting access for or another configuration parameter.
I suggest to check carefully the scopes name, or maybe directly use the "copy" button from the Azure portal.
In my case it was a simple typo on a scope name.
Not sure if you figured the answer or not. When you used SPFx to request your own custom web api end point. there are couple steps:
request the permission so that you can go to SPO admin to approve the permission you request. for this case, the webApiPermissionRequests->resources needs to your AAD Application's Service Principal DisplayName. once you had AAD App create, you can run Get-AzureADServicePrincipal to get all your ServicePrincipal.
once you request the permission, from your code, you need to call AadHttpClient.getClient() to get aadHttpClient object based on the api resourceEndpoint you want, for this case, you need to pass your web api's Application ID URI which can be found from your AAD App's manifest->"identifierUris". General speaking, this should be something like api://[clientid] format. but you can change it to any unique value.
I hope it helps.
In my case i had to use the App Id when i was consuming a multi tenant API.
In my case, TenantId and ClientId were both ok.
They can be found in AAD. TenantId is right there on landing page:
and then on the same page click Applications then tab All Applications find your application there should be ClientId check if they match.
If that is still not enough, click on the application and find roles
For me, it was roles that were missing after adding those wheels started rolling again:
I am trying to use Facebook's Javascript SDK to implement a login button in a Chrome extension's popup.html page.
However when I call the FB.login() function, I get the following error: Given URL is not allowed by the Application configuration. Now, since it's a Chrome extension, I am not sure if I can provide a URL or domain for it.
So, what should I do in such a case?
You need to manually build the login flow, as it is explained here:
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2
I'm building a login button for a chrome extension too, and I followed those instructions. However, whenever I try to access, I get this:
"Success
"SECURITY WARNING. Please use the url above as you would your password and do not share It with anyone."
This should be the right way... but I can't make It work. Maybe you can.
I am also trying to add fb-login feature in my chrome extension. I am using python-socialauth as authentication app for facebook in django app, which is the backend.
The steps I followed is as given below :
First I opened a window with facebook login link :
window.open('https://www.facebook.com/dialog/oauth?client_id=&response_type=token&redirect_uri=,"Facebook login", "width=635,height=290,left=0,top=0")
From the success url, I retrieved the access token and saved in chrome-local-storage.
Then I sent the token to my django-facebook-login view. But it is hitting error:
'Nonetype' object has no attribute 'encode'.
My code is as below :
if isinstance(request.backend, BaseOAuth1):
if request.REQUEST.get('backend') == "facebook":
oauth_token_secret = settings.SOCIAL_AUTH_FACEBOOK_KEY
if request.REQUEST.get('backend') == "google-oauth2":
oauth_token_secret = settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET
token = {
'oauth_token': request.REQUEST.get('access_token'),
'oauth_token_secret': oauth_token_secret,
}
elif isinstance(request.backend, BaseOAuth2):
token = request.REQUEST.get('access_token')
else:
raise HttpResponseBadRequest('Wrong backend type')
user = request.backend.do_auth(token, ajax=True)
# age = request.POST.get('age', '')
login(request, user)
The line where I am hitting error is :
user = request.backend.do_auth(token, ajax=True)
Trying out the Content Service API and the example is returning HTML when it should be returning JSON, what am I doing wrong?
https://developers.google.com/apps-script/guides/content
function doGet(request) {
var events = CalendarApp.getEvents(
new Date(Number(request.parameters.start) * 1000),
new Date(Number(request.parameters.end) * 1000));
var result = {
available: events.length == 0
};
return ContentService.createTextOutput(JSON.stringify(result))
.setMimeType(ContentService.MimeType.JSON);
}
GAS from another file trying to make the request:
function myFunction() {
var url = "published URL";
url+="?start=1325437200&end=1325439000";
var options = {
method:"get"
}
var response = UrlFetchApp.fetch(url,options).getContentText();
response = JSON.parse(response); //error, unexpected token <
}
Your usage of ContentService is correct, the code works exactly as is. Here is a link to my copy of your code published as a web app:
https://script.google.com/macros/s/AKfycbzx2L643LHw0oQAq1jBmKQh2ju_znGfmdj78dUypj36iF-s91w/exec
The problem you are running into is related to Authorization or Authentication, if the published script is not authorized, an HTML error message is returned.
To check if that is your issue, simply access the published URL directly in your browser. If you see JSON displayed, then Authorization is not the problem. If you see the "Authorization is required to perform that action" error message, open your published script and choose "doGet" from the Run menu, then follow the authorization prompts.
More likely, the problem is related to how your script is published. In order to access your published script from another script, it must be published with the "Who has access to the app" setting as "Anyone, Even anonymous". If you use any other value, Google returns an HTML login page instead of your JSON response, and you get the error you are seeing.
This happens because requests sent from Google Apps Script via URLFetchApp are not authenticated, they don't carry the credentials of the user running the code with them, and come in as anonymous requests.
If you don't allow "Anyone, even anonymous" in your publishing settings, Google redirects non-authenticated requests to the Google login page.
I am making a web app that pulls the latest posts from our Facebook page and processes them.
This is all working fine with a hard-coded access token generated from this page.
The problem is that this token expires, so i am looking for a solution to generate a new token every time the page loads or a non-expiring token - (i have read somewhere that non expiring tokens don't exist anymore).
So of course i did some research, here, here and here.
But non of these examples seem to be working.
Before any complaints of some code that i have tried so far, this is my working example - with an expiring access token:
var Facebook = function () {
this.token = 'MYTOKEN';
this.lastPost = parseInt((new Date().getTime()) / 1000);
this.posts = [];
};
Facebook.prototype.GetPosts = function () {
var self = this;
var deffered = $q.defer();
var url = 'https://graph.facebook.com/fql?q=SELECT created_time, message, attachment FROM stream WHERE created_time < ' + self.lastPost + ' AND source_id = 437526302958567 ORDER BY created_time desc LIMIT 5&?access_token=' + this.token + '';
$http.get(url)
.success(function (response) {
angular.forEach(response.data, function (post) {
self.posts.push(new Post(post.message, post.attachment.media, post.attachment.media[0].src, post.created_time, 'facebook'));
});
self.lastPost = response.data[response.data.length -1].created_time;
deffered.resolve(self.posts);
self.posts = [];
});
return deffered.promise;
};
return Facebook;
Any help / suggestion will be greatly appreciated.
First off, it is important to remember that Facebook has just launched the Version 2 of the Graph API. From April 2014 on, if you have issues with your app, you need to tell us when you created it on Facebook Developers (new apps use the Version 2 by default).
In order manage pages, your app needs to have manage_pages permission. Make sure that the user you want to manage fan pages for has authorized you. If your app uses the Version 2, make sure that Facebook (the Facebook staff) has authorized you to ask users that kind of permission, otherwise your app won't work.
Once you get your token, exchange it for a permanent token (or a token with long expiry date). Make sure you use the token of the fan page, not the token of the user.
If instead you want to read the stream of public fan pages, you need an access token with read_stream permissions. This permission needs to be approved by Facebook (see above) and this specific type of permission takes time to approve, if you're using the Version 2 of the Graph API. If you're using the old API (Version 1), you can still do that without pre-approval on Facebook's side.
The URL to ask for the permission to read the stream is as follows: https://www.facebook.com/dialog/oauth?client_id=$YOUR_APP_ID&redirect_uri=$YOUR_URL&scope=read_stream,manage_pages (i've added manage_pages in this case, you may not need it).
That url will prompt for authorization. Once the user has authorized the app, you'll be recirected to the URL you chose, with a code= variable.
At that point, call this other url:
https://graph.facebook.com/oauth/access_token?client_id={$app_id}&redirect_uri=$someurl&client_secret={$app_secret}&code={$code}
You'll get a response that has the access_token=variable in it. Grab that access token, exchange it for a long one, with the following URL:
https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&client_id={$app_id}&client_secret={$app_secret}&fb_exchange_token={$token_you_have_just_grabbed}
The response will give you a token that lasts for some time. Previously, Facebook had decided to have these "long duration tokens" expire after one month. I have found out, though, that they may have changed their mind: if you put a user token in the debugger, you'll see it never expires.
This is the authorization flow for users who visit with a browser. There's the app authorization flow too. If all you need is a stream from your own Fan page, you want to do the following (with Graph API V.1):
make an HTTP GET request using the following URL:
https://graph.facebook.com/oauth/access_token?type=client_cred&client_id={$app_id}&client_secret={$app_secret}
Use the resulting token to make another HTTP GET call, like so:
https://graph.facebook.com/{$your_page_id}/feed?{$authToken}&limit=10
//ten posts
Decode the json object
You're done.
stackoverflow'ers!
So my job now is to work around social networks. I've made login for facebook, google and twitter. Now i need to retrieve user avatars. Site is very dynamic and pretty much everything are working through javascript and ajax. I have got facebook user avatar successfully. When user has avatar, it returns avatar, when user has no avatar, it returns facebook's default avatar. Now im working on google-plus and twitter. I found nice url, where i can get avatar from google-plus:
https://plus.google.com/s2/photos/profile/{oauth_id}?sz=100
I am storing oauth_id in session, it is accessible.
When user has set avatar - everything works fine. Problem is, when users avatar is'nt set - that link returns 404 error.
How can i determine in jquery or just javascript, if that link returns 404 error or not?
And for some future work - i think twitter has the same problem.
Or may be you could provide some better options to achieve this.
Another way to do this is to request the plus.me scope, authenticate the user, then retrieve their profile which will have the image value set if they have an avatar. I created a live demo here: http://wheresgus.com/profile.html which shows profile retrieval using the Google+ public data API.
To set things up for your project, go to the Google APIs console - https://code.google.com/apis/console/ and create a project with the Google+ API enabled. You will need the Client ID for a web application from the API Access section of the Google APIs console.
The relevant code is as follows:
<html>
<head>
<script src="https://apis.google.com/js/plusone.js"></script>
<script type="text/javascript">
function onSignin(e){
accessToken = e.access_token;
var xhr = new XMLHttpRequest();
xhr.open('GET', "https://www.googleapis.com/plus/v1/people/me/");
xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
xhr.send();
xhr.onreadystatechange = function(){
if (this.readyState == 4){
var myProfile = JSON.parse(xhr.responseText);
alert(myProfile.image.url);
}
}
}
</script>
</head>
<body>
<g:plus action="connect" clientid="YOUR CLIENT ID" scope="https://www.googleapis.com/auth/plus.me" callback="onSignin">
</g:plus>
</body>
</html>
Create an HTML file with this code and replace YOUR CLIENT ID with the credentials you created in the Google APIs console. When you click the sign in button, the client will give you a URL for the user.
If you are using the jquery.ajax() or jquery.get() method (or something similar), you should be able to check the jqXHR object that is returned as part of the callback. It has a "status" field which contains the status code for the HTTP call.
See the section The jqXHR Object under http://api.jquery.com/jQuery.ajax/
I tried to fiddle around with the above suggestions but found the following approach suitable. I used jquery get to fetch the image url. Following is the code snippet.
function getImageURL(_gplusid) {
$.get("https://www.googleapis.com/plus/v1/people/"+_gplusid+"?fields=image"+"&key="+googlepluskey,
function (data) {
console.log(data);
});
}
P.S : _gplusid is the google plus id of the user and googlepluskey is your google authentication key. The output is a json object containing the image url. You need to enable google plus api access via google api console.