On a MVC 5 web site I would like visitors to be able to read the full version of a post only after they shared it on Facebook or Twitter.
I have seen this example in a few web sites ... What would be the best way to do this?
There is no real security issues here ... It is just a way to spread the word ...
My first idea would be to save a cookie with a post KEY (Guid) ... This key is not visible to the user so he will not know the value.
The problem is how do I know that he shared the url ... How do I get the confirmation?
Thank You,
Miguel
You get confirmation as follows, per the Facebook Developers Docs:
FB.ui(
{
method: 'feed',
name: 'Facebook Dialogs',
link: 'https://developers.facebook.com/docs/dialogs/',
picture: 'http://fbrell.com/f8.jpg',
caption: 'Reference Documentation',
description: 'Dialogs provide a simple, consistent interface for applications to interface with users.'
},
function(response) {
if (response && response.post_id) {
alert('Post was shared.'); //give access to article
} else {
alert('Post was not shared.'); //they chose not share... don't give access
}
});
I implemented this code almost verbatim in a .NET project (just replaced the alerts with my own functionality) where I gave users two entries into a contest if they shared the contest page (instead of one entry if they didn't share or did nothing).
As for Twitter, I've personally not implemented something similar, but your best bet is probably JavaScript Interfaces for Twitter for Websites.
I don't know about Facebook, but with Twitter a retweet is the same as a share. The statuses/retweeters/ids should work. If you have the id of the tweet, then you can hold a list of who retweeted it, updating as needed to get new ids.
https://dev.twitter.com/docs/api/1.1/get/statuses/retweeters/ids
If you don't want to write all of the code to authenticate and configure the endpoint, you could use a 3rd party library. Here's an example from my library, LINQ to Twitter v3.0 Beta:
ulong tweetID = 210591841312190464;
var status =
await
(from tweet in twitterCtx.Status
where tweet.Type == StatusType.Retweeters &&
tweet.ID == tweetID
select tweet)
.SingleOrDefaultAsync();
if (status != null && status.User != null)
status.Users.ForEach(
userID => Console.WriteLine("User ID: " + userID));
BTW, there's also a Facebook SDK for .NET.
Related
At my current project, we are using Auth0 as our Identity Provider. The current architecture is just a ReactJS app supported by a couple of APIs. Each API requires different combinations of Authorization Scopes, but basically they will require Customer Role, Provider Role or any authenticated user.
We were using Username-Password-Authentication so far and now we are integrating Social logins (such as Facebook, Google and Apple).
In order to achieve so, we are using Authorization Code flow, so the BE constructs the Authorize URL (including Callback URL, scopes, etc) that the FE then uses. After the user has authenticated against the Social Provider, the Callback URL is called, we exchange the code for an access_token that is ultimately returned to the FE. So far so good.
https://{domain}.auth0.com/authorize?
response_type=code&
client_id={clientId}&
audience={audience}&
connection=facebook&
state={ramdom_value}&
redirect_uri={callbackUrl}&
scope=offline_access openid scope:customer
And here is where some issues arise.
Firstly, after exchanging the Authentication Code for an access_token, the token does not include the scopes in it, so the user cannot access the APIs. I had to create a custom rule that adds the Customer role, like this:
function (user, context, callback) {
var count = context.stats && context.stats.loginsCount ? context.stats.loginsCount : 0;
if (count > 1 || (context.connection !== 'facebook' && context.connection !== 'google-oauth2' && context.connection !== 'apple')) {
return callback(null, user, context);
}
var ManagementClient = require('auth0#2.17.0').ManagementClient;
var management = new ManagementClient({
token: auth0.accessToken,
domain: auth0.domain
});
management.assignRolestoUser(
{ id : user.user_id},
{ "roles" :["rol_Msm9ykmstuK09r9s"]},
function (err) {
if (err) {
callback(err);
} else {
callback(null, user, context);
}
}
);
}
I don't really understand why I need to create the rule in order to get a valid access_token.
Secondly, there are two possible roles for users, Customers and Providers. For now, we are only allowing customers to use Social Logins, but eventually we will need to support also Providers. There is no way for us to detect what kind of user is actually logging in within that rule.
So my question here would be how to solve it.
My final goal is to allow users (both Customers and Providers) to log in using Social Connections and have each of them with the roles they really require. Of course, I need to get a valid access_token so that users can then interact with our APIs.
Any thoughts or comments? What am I missing?
I came up with an elegant solution after all.
The approach I took was:
Create a Custom Rule that assigns both roles (Customer and Provider) only and only if:
1.1. This is the first login for this user
1.2. The connection type is either facebook or google-oauth2 or apple
When creating the URL for login, include only the scopes required based on the user role required. In addition, the callback url will include the user role in it, e.g. https://server/{platform}/callback/{role}
In the callback endpoint, remove the roles that are not required using the Auth0 Management API /api/v2/users/{id}/roles
This solution is a bit tricky, but works with relatively small coding and effort.
I'm trying to post to a Facebook page AS the page using the Unity Facebook SDK running on iOS. As I understand, to do that, I need the pages access token with manage_pages and publish_pages. I know that I can get it from /me/accounts?fields=access_token, but how do I tell AccessToken.CurrentAccessToken to use my pages access token instead?
Right now i'm using the following:
var wwwForm = new WWWForm();
//wwwForm.AddField ("access_token", "A-T I NEED");
wwwForm.AddBinaryData("image", screenshot, "InteractiveConsole.png");
wwwForm.AddField("message", "herp derp. I did a thing! Did I do this right?");
FB.API("/PAGE-ID/photos", HttpMethod.POST, HandleResult, wwwForm);
I tried putting the access token manually, but that didn't work (so I commented it out).
With this as it is I'm getting an error, telling me that I need publish_actions, wich is not correct since I'm not trying to post as the user. If I also get publish_actions the Post goes online, but is posted to the page as the user speaking. (User is also Admin)
Any Ideas ? Thanks!
So, I filed a bug report to facebook and as it turns out: "… at this time this functionality is not supported." Wich simply means there is now way to use the Page Access Token you acquired via the FB.API within the FB.API. And they are not going to tell you abot it in the documentation.
As a workaround I simply use a UnityWebRequest like this:
IEnumerator UploadToPage(byte[] screenshot) {
var wwwForm = new WWWForm();
wwwForm.AddField("message", "herp derp. I did a thing! Did I do this right?");
wwwForm.AddBinaryData("image", screenshot, "Test.png");
string url = "https" + "://graph.facebook.com/"+ PageID + "/photos";
url += "?access_token=" + PageAccessToken;
using (UnityWebRequest www = UnityWebRequest.Post(url, wwwForm))
{
yield return www.Send();
if (www.isError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Form upload complete!");
}
}
Debug.Log(url);
}
Time ago I have this code to put the 3 last tweets of an user:
jQuery.getJSON("http://twitter.com/statuses/user_timeline/"+ user +".json?callback=?&count=3", function(data) {
jQuery.each(data, function(i, object) {
var textt = object.text.linkify().atify().hashify();
jQuery("#twitter").append('<p><span class="text">' + textt + '</span><br/><span class="quan">' +parseTwitterDate(object.created_at) + '</span></p><hr/>');
});
});
Now, I read that API have changed for a new URL and needs to create an App with secure token (Oauth) for let to see tweets on a site.
I've created the App with the user that I would like to shown the tweets and I have the secure keys, but How I can show now the tweets? I need to put this keys on some line of Javascript code? But with Javascript I can't put this keys because are secrets...
In short: you need a OAuth authentication before you can use the 1.1 API. The only way is to implement this step server side and pull the feed from there with Javascript. While doing this caching the feed increases page load.
Remember to check out the display REQUIREMENTS from twitter. Really, yes really!
I've been working on a solution. In my search I found the following resources very helpful:
https://dev.twitter.com/docs/api/1.1
http://www.jaisenmathai.com/articles/twitter-async-documentation.html
In my asp.net MVC app, I'm trying to know if this is facebook who is calling one of my urls (when a link to my site is shared as a FB status and FB tries to get some meta tags for opengraph). I have tried URlReferrer, which is empty, and UserHostName which shows an IP addr.
You could do as Tejs suggests, something like:
IPHostEntry IpEntry = Dns.GetHostByAddress(HttpContext.Current.Request.UserHostAddress);
//OR
IPHostEntry IpEntry = Dns.GetHostByAddress(HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]);
if(IpEntry.HostName.Contains("facebook.com"))
{
//Coming from facebook.com
}
Seems like this can be done like so:
if ((!string.IsNullOrWhiteSpace(HttpContext.Request.UserAgent) && HttpContext.Request.UserAgent.ToLower().Contains("facebookexternalhit")) ||
((HttpContext.Request.UrlReferrer != null) && HttpContext.Request.UrlReferrer.Host.ToLower().Contains("facebook.com")))
This way I know if Facebook is grabbing opengraph data or if someone clicks the shared link from a facebook page.
I am trying to access a tweet conversation history using TweetSharp.
The requirement is like, if I use id of one tweet item it should
return me the whole thread that followed before that tweet item.
But could not find such method exposed through TwittertService, where
I can pass the current Tweet _id and get the conversation details.
I followed the following approach to get the collection (list) ie,
List<TwitterStatus> list = new List<TwitterStatus>();
private void GetReplied(TwitterStatus twitter, TwitterResponse twitterResponse)
{
if (twitter.InReplyToStatusId != null)
{
long statusID = (long)twitter.InReplyToStatusId;
this.ts.GetTweet(statusID, (twitterRecursive,
twitterResponseRecursive) =>
{
list.Add(twitterRecursive);
if (twitter.InReplyToStatusId != null)
{
this.GetReplied(twitterRecursive,
twitterResponseRecursive);
}
});
}
else
{
Debug.WriteLine(list.Count);
foreach (TwitterStatus status in list)
{
Debug.WriteLine(status.Text);
}
}
}
this.ts.GetTweet(<tweet Id>, twitterResponse) =>
{
list.Add(twitter);
this.GetReplied(twitter, twitterResponse);
});
Just wanted to have your advice, on that. Do we have any such method
with TweetSharp or any alternative approach can be implemented?
Really appreciate your help.
Yep, that's how you'll have to do it: start with a tweet and walk its in_reply_to_status_id chain.
One thing I do, although it may not be applicable to you, is check a local cache of tweets before fetching from Twitter to see if I already fetched the tweet being replied to.
As for libraries that make this easier, I don't know of any. Regardless of whether they expose a more streamlined method, under the covers they'll still have to perform the process that you implemented in your code.
To see how another library approached this task, take a look at this Twitterizer sample.