Using Facebook graph in Chrome Extensions - facebook

I'm trying to use Facebook graph in Chrome extensions, but I'm having trouble in using access token to have permissions. My extension folder has a background.html file with the this code:
function displayUser(user) {
var userName = document.getElementById('userName');
var greetingText = document.createTextNode('Greetings, ' + user.name + '.');
userName.appendChild(greetingText);
}
var appID = "XXXXX";
if (window.location.hash.length == 0) {
var path = 'https://www.facebook.com/dialog/oauth?';
var queryParams = ['client_id=' + appID,'redirect_uri=https://www.facebook.com/connect/login_success.html', 'response_type=token'];
var query = queryParams.join('&');
var url = path + query;
window.open(url);
} else {
var accessToken = window.location.hash.substring(1);
var path = "https://graph.facebook.com/me?";
var queryParams = [accessToken, 'callback=displayUser'];
var query = queryParams.join('&');
var url = path + query;
// use jsonp to call the graph
var script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
}
When I run the extension, it opens a new tab with the app authorization. When I accept it, it just says "Success" and the url of this tab is like this:
https://www.facebook.com/connect/login_success.html#access_token=AAABtoJwdQQgBAP8KK6QYmlQ1CJOSjQxWjXoa7qgUthF507BGPgLeWEplB87fZBpDZBZBd7CKoIWb4Fa3S2laBuZAUf795p1N3QZDZD&expires_in=5549
So now how can I use this access token in background.html and close that authorization tab?

You should watch (in the extension code) for the tab changes with success url like this
chrome.tabs.onUpdated.addListener(onTabUpdated);
Then the handler function:
function onTabUpdated(tabId, changeInfo, tab) {
if (changeInfo.url && changeInfo.url.indexOf(SUCCESS_URL) == 0) {
// extract access token from url
Extract function:
function accessTokenFromSuccessURL(url) {
var hashSplit = url.split('#');
if (hashSplit.length > 1) {
var paramsArray = hashSplit[1].split('&');
for (var i = 0; i < paramsArray.length; i++) {
var paramTuple = paramsArray[i].split('=');
if (paramTuple.length > 1 && paramTuple[0] == 'access_token')
return paramTuple[1];
}
}
return null;
}

Judging by redirect_uri=https://www.facebook.com/connect/login_success.html, I'm assuming you're building a desktop or a client side app.
Try adding var RedirectURI = window.location;
And change the redirect URI in the queryParams array to redirect_uri= RedirectURI
If required, you can add http://localhost to the Site URL entry in https://developers.facebook.com/apps
Once the token is obtain, it is redirected to your previous page with the authorization token added as a hash which is automatically handled by the else { } block in your code.

Related

Javascript injection goes wrong

In our Android project (download manager) we need to show built-in web browser so we able to catch downloads there with the all data (headers, cookies, post data) so we can handle them properly.
Unfortunately, WebView control we use does not provide any way to access POST data of the requests it makes.
So we use a hacky way to get this data. We inject this javascript code in the each html code the browser loads:
<script language="JavaScript">
HTMLFormElement.prototype._submit = HTMLFormElement.prototype.submit;
HTMLFormElement.prototype.submit = formSubmitMonitor;
window.addEventListener('submit', function(e) {
formSubmitMonitor(e);
}, true);
function formSubmitMonitor(e) {
var frm = e ? e.target : this;
formSubmitMonitor_onsubmit(frm);
frm._submit();
}
function formSubmitMonitor_onsubmit(f) {
var data = "";
for (i = 0; i < f.elements.length; i++) {
var name = f.elements[i].name;
var value = f.elements[i].value;
//var type = f.elements[i].type;
if (name)
{
if (data !== "")
data += '&';
data += encodeURIComponent(name) + '=' + encodeURIComponent(value);
}
}
postDataMonitor.onBeforeSendPostData(
f.attributes['method'] === undefined ? null : f.attributes['method'].nodeValue,
new URL(f.action, document.baseURI).href,
data,
f.attributes['enctype'] === undefined ? null : f.attributes['enctype'].nodeValue);
}
XMLHttpRequest.prototype.origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
// these will be the key to retrieve the payload
this.recordedMethod = method;
this.recordedUrl = url;
this.origOpen(method, url, async, user, password);
};
XMLHttpRequest.prototype.origSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
if (body)
{
postDataMonitor.onBeforeSendPostData(
this.recordedMethod,
this.recordedUrl,
body,
null);
}
this.origSend(body);
};
const origFetch = window.fetch;
window.fetch = function()
{
postDataMonitor.onBeforeSendPostData(
"POST",
"test",
"TEST",
null);
return origFetch.apply(this, arguments);
}
</script>
Generally, it works fine.
But in Google Mail web interface, it's not working for some unknown reason. E.g. when the user enters his login name and presses Next. I thought it's using Fetch API, so I've added interception for it too. But this did not help. Please note, that we do not need to intercept the user credentials, but we need to be able to intercept all, or nothing. Unfortunately, this is the way the whole system works there...
Addition #1.
I've found another way: don't override shouldInterceptRequest, but override onPageStarted instead and call evaluateJavascript there. That way it works even on Google Mail web site! But why the first method is not working then? We break HTML code somehow?

How to find out permissions for each tree element(folder or file) for another user using sharepoint api?

I want to get answer for question:
Does userA can read the folder/tree ?
Application uses another user to communicate with sharpoint via sharepoint API.
I've googled the following request:
http://aissp2013/sites/Team/_api/web/lists/getbytitle('L2')/EffectiveBasePermissions
But it doesn't resolve my problem because it responds with permissions for current user!
Is there way to get permissions for another user for concrete element(folder or file or library)
Is there way to get permissions for another user for all elements and sub-elements ?
To get permissions per user SP.ListItem.getUserEffectivePermissions method is intended:
for SP.Folder
Url /_api/web/getFolderByServerRelativeUrl('<folder-rel-url>')/ListItemAllFields/getusereffectivepermissions(#u)?#u='<account>'
Method: Get
for SP.File
Url /_api/web/getFileByServerRelativeUrl('<file-rel-url>')/ListItemAllFields/getusereffectivepermissions(#u)?#u='<account>'
Method: Get
Note: account parameter needs to be provided in claims format
Regarding the question:
Does userA can read the folder/tree ?
the following example demonstrates how to retrieve permissions for a folder
const accountName = "i:0#.f|membership|<name>#<tenant>.onmicrosoft.com";
let endpointUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/getFolderByServerRelativeUrl('/Shared Documents/Achive')/ListItemAllFields/getusereffectivepermissions(#u)?#u='" + encodeURIComponent(accountName) + "'";
const content = await executeJson(endpointUrl);
let roles = parseBasePermissions(content.d.GetUserEffectivePermissions);
if(roles.viewListItems)
console.log(`${accountName} has been granted permissions.`);
where
function parseBasePermissions(value)
{
let permissions = new SP.BasePermissions();
permissions.initPropertiesFromJson(value);
let result = {};
for(var levelName in SP.PermissionKind.prototype) {
if (SP.PermissionKind.hasOwnProperty(levelName)) {
var permLevel = SP.PermissionKind.parse(levelName);
if(permissions.has(permLevel))
result[levelName] = true;
else
result[levelName] = false;
}
}
return result;
}
is used to parse permission mask into roles
and
async function executeJson(url,options) {
options = options || {};
options.method = options.method || 'GET';
options.headers = options.headers || {};
options.headers["Accept"] = "application/json;odata=verbose";
options.headers["Content-Type"] = "application/json;odata=verbose";
if(options.method == "POST") {
options.headers["X-RequestDigest"] = document.getElementById("__REQUESTDIGEST").value;
}
if (options.body) {
options.body = JSON.stringify(options.body);
}
const rawResponse = await fetch(url,options);
const content = await rawResponse.json();
return content;
}
to perform REST request

Change filename of existing file on SharePoint Document library using REST API

I have a question on how to change an existing file on SharePoint document library using REST API. I have a couple of files in the location http://site url/<RootFolder>/<SubFolder>/File.docx. I have a UI where it lists all the files from this subfloder location. When the user clicks on edit i am enabling the file name as textbox where the user can change the name of the file.
After doing some research i found that Constructing an endpoint that looks like this: https://<site url>/_api/web/lists/getbytitle('Documents')/items(<item id>) we can edit the file metadata properties. But i could not able to figure out the best way to update the filename of existing document that resides on SharePoint Doc library.
Could someone please help me with the REST API query to fetch the file and the approach to update the filename?
You could consider at least two options:
Option 1. Rename file name
You could update the name of the existing list item as demonstrated below
Example
function rename(webUrl,listTitle,itemId,fileName){
var endpointUrl = webUrl + "/_api/web/lists/getbytitle('" + listTitle + "')/items(" + itemId + ")";
return executeJson(endpointUrl)
.then(function(data){
var itemPayload = {};
itemPayload['__metadata'] = {'type': data.d['__metadata']['type']};
itemPayload['Title'] = fileName;
itemPayload['FileLeafRef'] = fileName;
var itemUrl = data.d['__metadata']['uri'];
var headers = {};
headers["X-HTTP-Method"] = "MERGE";
headers["If-Match"] = "*";
return executeJson(itemUrl,"POST",headers,itemPayload);
});
}
var webUrl = _spPageContextInfo.webAbsoluteUrl; // web url
var listTitle = "Documents"; //list title
var itemId = 1; //list item id
var fileName = "SP User Guide.docx"; //new file name
rename(webUrl,listTitle,itemId,fileName)
.done(function(item){
console.log('Renamed');
})
.fail(function(error){
console.log(error);
});
Option 2. Move file via MoveTo REST endpoint
Example
function moveTo(webUrl,sourceFileUrl,targetFileUrl){
var endpointUrl = webUrl + "/_api/web/getfilebyserverrelativeurl('" + sourceFileUrl + "')/moveto(newurl='" + targetFileUrl + "',flags=1)";
return executeJson(endpointUrl,"POST");
}
var webUrl = _spPageContextInfo.webAbsoluteUrl; // web url
var sourceFileUrl = "/Documents/SP2010.docx";
var targetFileUrl = "/Documents/SP2013.docx";
moveTo(webUrl,sourceFileUrl,targetFileUrl)
.done(function(item){
console.log('Done');
})
.fail(function(error){
console.log(error);
});
executeJson function:
function executeJson(url,method,headers,payload)
{
headers = headers || {};
method = method || 'GET';
headers["Accept"] = "application/json;odata=verbose";
if(method == "POST") {
headers["X-RequestDigest"] = $("#__REQUESTDIGEST").val();
}
var ajaxOptions =
{
url: url,
type: method,
contentType: "application/json;odata=verbose",
headers: headers
};
if(method == "POST") {
ajaxOptions.data = JSON.stringify(payload);
}
return $.ajax(ajaxOptions);
}
You need to use the MoveTo Method to do this as described here in MSDN https://msdn.microsoft.com/en-us/library/office/dn450841.aspx#bk_FileMoveTo.
executor.executeAsync({
url: "<app web url>/_api/SP.AppContextSite(#target)/web
/getfilebyserverrelativeurl('/Shared Documents/filename.docx')
/moveto(newurl='/Other Folder/filename.docx',flags=1)
?#target='<host web url>'",
method: "POST",
success: successHandler,
error: errorHandler
});

How to play secure streamed url of asset fetched dynamically through code( In Azure media services)

I am using Azure Media Services and a Silverlight Player to play the streamed url
I am able to ingest, encode the video file as an asset file but when I go play the streamed url I am facing problem.
I use following code to fetch the url...
context = new CloudMediaContext(_accountName, _accountKey);
IAsset myAsset = GetAsset("UUID:7a32b941-30bd-4c96-bf4e-26df5022eec5");
var theManifest = from f in myAsset.AssetFiles
where f.Name.EndsWith(".ism")
select f;
var manifestFile = theManifest.First();
IAccessPolicy streamingPolicy = _context.AccessPolicies.Create("Streaming policy",
TimeSpan.FromDays(10),
AccessPermissions.Read);
ILocator originLocator = _context.Locators.CreateSasLocator(myAsset, streamingPolicy, DateTime.UtcNow.AddMinutes(-500));
GetAssetSasUrlList(myAsset, originLocator);
string urlForClientStreaming = originLocator.Path + manifestFile.Name + "/manifest";
Console.WriteLine("URL to manifest for client streaming: ");
Console.WriteLine(urlForClientStreaming);
this url comes like --
https://mediasvc06w4dq5k8vd08.blob.core.windows.net/asset-064ed2d5-e42d-4c49-98eb-a712db5c614f?st=2012-12-26T23%3A04%3A22Z&se=2013-01-05T23%3A04%3A22Z&sr=c&si=9350bd2f-ec23-40b2-b27a-248bba01b97e&sig=oGgesnr8mXjCdTM5Dz%2FQpFRBDR0g0%2F60ECoXY14EvsA%3DBigBuckBunny.ism/manifest
Its not working .
When I paste this url on browser directly ,I get following error
AuthenticationFailedServer failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:154422cf-822e-4bbc-af2a-fa69273dfb89 Time:2012-12-27T08:57:30.9509847ZSignature fields not well formed.
But if I go and publish asset from portal( www.manage.windowsazure.com )--
I get like following url on protal..
http://mediaervices.origin.mediaservices.windows.net/5edbeae7-c3e6-45c5-bc5c-70f46b526cb5/BigBuckBunny.ism/Manifest
And it works with my silverlight player..
Now problem is that I am not getting url which starts with http from code and the url starting with https is not working with my player.
I guessed that its security issue and tried to host my player in winows azure and tried to player there but no success.
No, not a security issue. You are requesting a SAS url for a Smooth asset, you need an Origin URL. The correct code snippet is here, on my blog:
http://blog-ndrouin.azurewebsites.net/?p=1931
Specifically:
private static string GetStreamingUrl(CloudMediaContext context, string outputAssetId)
{
var daysForWhichStreamingUrlIsActive = 365;
var outputAsset = context.Assets.Where(a => a.Id == outputAssetId).FirstOrDefault();
var accessPolicy = context.AccessPolicies.Create(outputAsset.Name, TimeSpan.FromDays(daysForWhichStreamingUrlIsActive), AccessPermissions.Read | AccessPermissions.List);
var assetFiles = outputAsset.AssetFiles.ToList();
var assetFile = assetFiles.Where(f => f.Name.ToLower().EndsWith("m3u8-aapl.ism")).FirstOrDefault();
if (assetFile != null)
{
var locator = context.Locators.CreateLocator(LocatorType.OnDemandOrigin, outputAsset, accessPolicy);
Uri hlsUri = new Uri(locator.Path + assetFile.Name + "/manifest(format=m3u8-aapl)");
return hlsUri.ToString();
}
assetFile = assetFiles.Where(f => f.Name.ToLower().EndsWith(".ism")).FirstOrDefault();
if (assetFile != null)
{
var locator = context.Locators.CreateLocator(LocatorType.OnDemandOrigin, outputAsset, accessPolicy);
Uri smoothUri = new Uri(locator.Path + assetFile.Name + "/manifest");
return smoothUri.ToString();
}
assetFile = assetFiles.Where(f => f.Name.ToLower().EndsWith(".mp4")).FirstOrDefault();
if (assetFile != null)
{
var locator = context.Locators.CreateLocator(LocatorType.Sas, outputAsset, accessPolicy);
var mp4Uri = new UriBuilder(locator.Path);
mp4Uri.Path += "/" + assetFile.Name;
return mp4Uri.ToString();
}
return string.Empty;
}

Get Facebook iframe params

If a user clicks 'Accept' on a request, they will see an iframe with my site in it.
The facebook url (that has the iframe), looks something like this:
https://apps.facebook.com/[request_id]/?fb_source=notification&request_ids=[request_ids]&ref=notif&app_request_type=user_to_user&notif_t=app_request
How can i get the 'request_id' from the iframe url??
Is there a method/API for that in the JS library?
If you are using php
you can retrieve request_id by $_GET['request_id'] or $_REQUEST['request_id']
if you are using javascript
This is just one implementation of getting requests parameters in javascript, there are better implementations as well, i stated an example.
var Request = {
parameter: function(name) {
return this.parameters()[name];
},
parameters: function() {
var result = {};
var url = window.location.href;
var parameters = url.slice(url.indexOf('?') + 1).split('&');
for(var i = 0; i < parameters.length; i++) {
var parameter = parameters[i].split('=');
result[parameter[0]] = parameter[1];
}
return result;
}
}
var request_id = parameters['request_id'];
Get url from iframe
document.getElementById("iframe_id").contentWindow.location.href
Hope this is what you require