Facebook Connect and ASP.NET - asp.net

I'm at step 8 of the authentication overview found here: http://wiki.developers.facebook.com/index.php/How_Connect_Authentication_Works
In particular, the user has logged into facebook via Facebook Connect and their web session has been created. How do I use the facebook developer toolkit v2.0 (from clarity) to retrieve information about the user. For example, I'd like to get the user's first name and last name.
Examples in the documentation are geared towards facebook applications, which this is not.
Update
Facebook recently released the Graph API. Unless you are maintaining an application that is using Facebook Connect, you should check out the latest API: http://developers.facebook.com/docs/

I had a lot of trouble figuring out how to make server side calls once a user logged in with Facebook Connect. The key is that the Facebook Connect javascript sets cookies on the client once there's a successful login. You use the values of these cookies to perform API calls on the server.
The confusing part was looking at the PHP sample they released. Their server side API automatically takes care of reading these cookie values and setting up an API object that's ready to make requests on behalf of the logged in user.
Here's an example using the Facebook Toolkit on the server after the user has logged in with Facebook Connect.
Server code:
API api = new API();
api.ApplicationKey = Utility.ApiKey();
api.SessionKey = Utility.SessionKey();
api.Secret = Utility.SecretKey();
api.uid = Utility.GetUserID();
facebook.Schema.user user = api.users.getInfo();
string fullName = user.first_name + " " + user.last_name;
foreach (facebook.Schema.user friend in api.friends.getUserObjects())
{
// do something with the friend
}
Utility.cs
public static class Utility
{
public static string ApiKey()
{
return ConfigurationManager.AppSettings["Facebook.API_Key"];
}
public static string SecretKey()
{
return ConfigurationManager.AppSettings["Facebook.Secret_Key"];
}
public static string SessionKey()
{
return GetFacebookCookie("session_key");
}
public static int GetUserID()
{
return int.Parse(GetFacebookCookie("user"));
}
private static string GetFacebookCookie(string name)
{
if (HttpContext.Current == null)
throw new ApplicationException("HttpContext cannot be null.");
string fullName = ApiKey() + "_" + name;
if (HttpContext.Current.Request.Cookies[fullName] == null)
throw new ApplicationException("Could not find facebook cookie named " + fullName);
return HttpContext.Current.Request.Cookies[fullName].Value;
}
}

I followed up on this concept and wrote a full fledged article that solves this problem in ASP.NET. Please see the following.
How to Retrieve User Data from Facebook Connect in ASP.NET - Devtacular
Thanks to Calebt for a good start on that helper class.
Enjoy.

Facebook Connect actually isn't too difficult, there's just a lack of documentation.
Put the necessary javascript from here: http://tinyurl.com/5527og
Validate the cookies match the signature provided by facebook to prevent hacking, see: http://tinyurl.com/57ry3s for an explanation on how to get started
Create an api object (Facebook.API.FacebookAPI)
On the api object, set the application key and secret Facebook provides you when you create your app.
Set api.SessionKey and api.UserId from the cookies created for you from facebook connect.
Once that is done, you can start making calls to facebook:
Facebook.Entity.User user = api.GetUserInfo(); //will get you started with the authenticated person

This is missing from the answers listed so far:
After login is successful, Facebook recommends that you validate the cookies are in fact legit and placed on the client machine by them.
Here is two methods that can be used together to solve this. You might want to add the IsValidFacebookSignature method to calebt's Utility class. Notice I have changed his GetFacebookCookie method slightly as well.
private bool IsValidFacebookSignature()
{
//keys must remain in alphabetical order
string[] keyArray = { "expires", "session_key", "ss", "user" };
string signature = "";
foreach (string key in keyArray)
signature += string.Format("{0}={1}", key, GetFacebookCookie(key));
signature += SecretKey; //your secret key issued by FB
MD5 md5 = MD5.Create();
byte[] hash = md5.ComputeHash(Encoding.UTF8.GetBytes(signature.Trim()));
StringBuilder sb = new StringBuilder();
foreach (byte hashByte in hash)
sb.Append(hashByte.ToString("x2", CultureInfo.InvariantCulture));
return (GetFacebookCookie("") == sb.ToString());
}
private string GetFacebookCookie(string cookieName)
{
//APIKey issued by FB
string fullCookie = string.IsNullOrEmpty(cookieName) ? ApiKey : ApiKey + "_" + cookieName;
return Request.Cookies[fullCookie].Value;
}
The SecretKey and ApiKey are values provided to you by Facebook. In this case these values need to be set, preferably coming from the .config file.

I followed up from Bill's great article, and made this little component. It takes care of identifying and validating the user from the Facebook Connect cookies.
Facebook Connect Authentication for ASP.NET
I hope that helps somebody!
Cheers,
Adam

You may also use SocialAuth.NET
It provides authentication, profiles and contacts with facebook, google, MSN and Yahoo with little development effort.

My two cents: a very simple project utilizing the "login with Facebook" feature - facebooklogin.codeplex.com
Not a library, but shows how it all works.

Related

Google Apps Admin Settings API - 401

I'm trying to get the Organization name for a Google Apps domain. For this, I'm using the Google Apps Admin Settings API. I saw that it required 3-Legged OAuth. I try to implement OAuth 2.0 because OAuth 1 is deprecated. I try many thing to get this work but I'm always getting a 401 unautorized.
I request a token for the scope : https://apps-apis.google.com/a/feeds/domain/
Here is my code:
// ClientID & ClientSecret values
var requestFactory = GDAPI.GoogleApps.GetAuthRequestFactory();
string organizationName = String.Empty;
Google.GData.Apps.AdminSettings.AdminSettingsService service =
new Google.GData.Apps.AdminSettings.AdminSettingsService(auth.Domain, Excendia.Mobility.Utilities1.BLL.WebConfig.ExcendiaAppName);
service.RequestFactory = requestFactory;
service.SetAuthenticationToken(token);
try
{
var result = service.GetOrganizationName(); // throw exception here...
}
catch (Exception ex)
{
log.Error(ex);
}
What am I doing wrong?
Is this compatible with OAuth 2?
I also want to ask if there is another way to get organization name because GData library is supposed to be obsolete and replaced by new Google.Apis...
Resolved!
Thanks Jay. It works on OAuth 2.0 playground. Something on my side was not set correctly.
Using Fiddler I saw the Authorization header being set by my application. It was set to OAuth v1 instead of v2. So I found out I was using the wrong RequestFactory class.
Need to use GOAuth2RequestFactory instead of GOAuthRequestFactory...
So this is now working:
string organizationName = String.Empty;
Google.GData.Apps.AdminSettings.AdminSettingsService service =
new Google.GData.Apps.AdminSettings.AdminSettingsService(auth.Domain, "myAppName");
service.RequestFactory =
new Google.GData.Client.GOAuth2RequestFactory("cl", "MyAppName",
new Google.GData.Client.OAuth2Parameters()
{ ClientId = ClientID,
ClientSecret = ClientSecret,
AccessToken = token });
try
{
var result = service.GetOrganizationName();
if (result != null)
{
organizationName = result.OrganizationName;
}
}
catch (Exception ex)
{
log.Error(ex);
}
return organizationName;
You are using the correct API. Though GData is being replaced by the new Google APIs, Admin Settings API still uses the old GData format for now.
Are you using a super administrator account to authenticate with? Can you try the operation on the OAuth 2.0 playground and see if it works for the account there?
You can also take a look at how Dito GAM, an open source Google Apps tool implements this call. If you create a file named debug.gam in the same path as GAM, GAM will print out all the raw HTTP calls and responses it's making/getting.

How can I show the latest Tweets on a particular subject in asp.net?

I want to add a section to a web page that will contain a scrolling list of the latest Tweets on a particular subject. How can this be accomplished?
If it is always the same subject, would it be as easy as embedding a web page within a web page with the URL:
http://topsy.com/s?q=%23marktwain
(replacing "marktwain" with whatever the subject is)?
You can use Tweetsharp to leverage the twitter api
you can create an embedded timeline or you could try out live tweet - a jquery plugin
One of the issues you'll face is the need to use OAuth on all your queries, which is required by Twitter API v1.1. Twitter has deprecated v1.0 of the API and will start doing blackouts before shutting it down next month. I don't see any Web page widgets on Twitter's Web page to do this either.
If you embedded this in a Web page, you would need a JavaScript OAuth library, which also means that your credentials must be in your Web page - an insecure approach.
Silverlight is a possibility, but Microsoft's focus on HTML/JavaScript leaves it's future in a questionable state. Besides, someone could also decompile the component and get your credentials, which is also not secure.
This leaves a server-side solution as the best possibility. You could handle this via pull or push. SignalR would be a good approach for push, but the tradeoff is that you need a continuously running process for immediate updates. If you run your own server, you could run a process via Windows Service that either does periodic Search queries, or uses a Filter Stream and uses SignalR to push results to the page. In the pull approach, your page can run a timer with an Ajax query back to the server, collecting new tweets and displaying them on the page. These are just a couple ideas, but provided to give you an idea of how you might approach the problem.
Twitter has a list of Libraries you can use. I wrote LINQ to Twitter, which also supports Twitter API v1.1.
I wrote something recently. Hope this helps. https://devtasks.blogspot.com/2013/06/console-app-that-displays-twitter-feed.html
using System;
using System.Linq;
using LinqToTwitter;
using System.Threading;
namespace Linq2Twitter
{
class Program
{
/// <summary>
/// Controls the flow of the program.
/// </summary>
/// <param name="args">The args.</param>
static void Main(string[] args)
{
// This is a super simple example that
// retrieves the latest tweets of a given
// twitter user.
// SECTION A: Initialise local variables
Console.WriteLine("SECTION A: Initialise local variables");
// Access token goes here .. (Please generate your own)
const string accessToken = "Access token goes here .. (Please generate your own)";
// Access token secret goes here .. (Please generate your own)
const string accessTokenSecret = "Access token secret goes here .. (Please generate your own)";
// Api key goes here .. (Please generate your own)
const string consumerKey = "Api key goes here .. (Please generate your own)";
// Api secret goes here .. (Please generate your own)
const string consumerSecret = "Api secret goes here .. (Please generate your own)";
// The twitter account name goes here
const string twitterAccountToDisplay = "roeburg";
// SECTION B: Setup Single User Authorisation
Console.WriteLine("SECTION B: Setup Single User Authorisation");
var authorizer = new SingleUserAuthorizer
{
CredentialStore = new InMemoryCredentialStore
{
ConsumerKey = consumerKey,
ConsumerSecret = consumerSecret,
OAuthToken = accessToken,
OAuthTokenSecret = accessTokenSecret
}
};
// SECTION C: Generate the Twitter Context
Console.WriteLine("SECTION C: Generate the Twitter Context");
var twitterContext = new TwitterContext(authorizer);
// SECTION D: Get Tweets for user
Console.WriteLine("SECTION D: Get Tweets for user");
var statusTweets = from tweet in twitterContext.Status
where tweet.Type == StatusType.User &&
tweet.ScreenName == twitterAccountToDisplay &&
tweet.IncludeContributorDetails == true &&
tweet.Count == 10 &&
tweet.IncludeEntities == true
select tweet;
// SECTION E: Print Tweets
Console.WriteLine("SECTION E: Print Tweets");
PrintTweets(statusTweets);
Console.ReadLine();
}
/// <summary>
/// Prints the tweets.
/// </summary>
/// <param name="statusTweets">The status tweets.</param>
/// <exception cref="System.NotImplementedException"></exception>
private static void PrintTweets(IQueryable<Status> statusTweets)
{
foreach (var statusTweet in statusTweets)
{
Console.WriteLine(string.Format("\n\nTweet From [{0}] at [{1}]: \n-{2}",
statusTweet.ScreenName,
statusTweet.CreatedAt,
statusTweet.Text));
Thread.Sleep(1000);
}
}
}
}

Does the Facebook C# SDK depend on cookies on the server?

I'm using the Facebook C# SDK and am trying to figure out exactly how it works. I actually use an AJAX web method to lookup the Facebook account details based on the authenticated user ID, which looks something like this:
if (response.status === "connected")
{
KitchenPC.LogonFB(response.authResponse.userID, checkResult, facebookError);
}
On the server side, the LogonFB web method does something like:
Client = new FacebookClient(applicationId, applicationSecret);
var result = Client.Get(path) as IDictionary<string, object>;
UserId = Int64.Parse((String)result["id"]);
Name = result["name"] as String;
FirstName = result["first_name"] as String;
LastName = result["last_name"] as String;
Location = result.ContainsKey("location") ? result["location"] as String : "";
Gender = result.ContainsKey("gender") ? result["gender"] as String : "";
Email = result["email"] as String;
Where path is the user ID passed in from the client.
My Question:
I'm switching from ASP.NET Web Service to WCF, and WCF does not support cookies. In fact, HttpContext.Current will be null within the WCF pipeline. I was under the impression that the Facebook C# SDK depended on the fbm_ and fmsr_ cookies being passed in on the request, which would be used to validate the session with the Facebook server. However, much to my surprise, the .Get() call still works, and user information is returned. I also dug through the SDK source code and nowhere in it do I find references to HttpContext.Current.
Does the Facebook C# SDK work completely independently of cookies? Does this mean that all I need is the user's Facebook ID, and as long as they've previously approved my app ID, I can grab information about their account?
I just want to make sure I'm not doing anything wrong, and I'm not going to run into trouble in production.
When you pass the constructor with appId and appSecret, it will auto set the access token as app access token using string.Concat(appId, '|', appSecret). That constructor has been removed in newer version of the sdk. https://github.com/facebook-csharp-sdk/facebook-csharp-sdk/issues/103
Set it to null if you don't want the access token.
Client = new FacebookClient(applicationId, applicationSecret);
Client.AccessToken = null;
var result = Client.Get(path) as IDictionary<string, object>;

Graph api, C# to share data from app to my wall

i am trying to develop an app which can allow me to share data on Facebook wall.
For eg: consider the Facebook Canvasapp "Run with Friends". This is a canvas app using Python and Php.
https://developers.facebook.com/docs/samples/. I will be able to share data from this app to my wall./me
Before doing this v need a access token. I was able to get the authorization, accesstoken using Graph api, Oauth2.0, C#, asp.net
public string AuthorizationLinkGet(bool bUserInfo, bool bFriends, bool bfeed, bool bPhotos, bool bEvents, bool bMessages)
{
string url = string.Format("{0}?client_id={1}&redirect_uri={2}", AUTHORIZE, this.ConsumerKey, CALLBACK_URL);
if (bUserInfo == true || bFriends == true || bfeed == true || bEvents == true || bPhotos == true || bMessages == true)
{
url += "&scope=email";
if (bUserInfo == true)
{
url += ",user_about_me,user_interests,user_likes,user_location,user_notes,user_education_history,user_hometown";
}
if (bFriends == true)
{
url += ",read_friendlists,user_groups";
}
if (bfeed == true)
{
url += ",read_stream";
}
if (bEvents == true)
{
url += ",user_events";
}
if (bEvents == true)
{
url += ",user_photo_video_tags";
}
if (bMessages == true)
{
url += ",read_mailbox";
}
}
return url;
}
<add key="APIKey" value="*************************"/>
<add key="Secret" value="**********************"/>
So now how do I be able to share data from the app onto my FB wall.
I've tried Sharekit but look like Sharekit is for mobile apps.
public void AccessTokenGet(string authToken)
{
this.Token = authToken;
string accessTokenUrl = string.Format("{0}?client_id={1}&redirect_uri={2}&client_secret={3}&code={4}",
ACCESS_TOKEN, this.ConsumerKey, CALLBACK_URL, this.ConsumerSecret, authToken);
string response = WebRequest(Method.GET, accessTokenUrl, String.Empty);
if (response.Length > 0)
{
//Store the returned access_token
NameValueCollection qs = HttpUtility.ParseQueryString(response);
if (qs["access_token"] != null)
{
this.Token = qs["access_token"];
}
}
}
does any one know how to develop this canvas app in C# using Graph Api
I have no idea abt all the curls and things in Php
Also, I see people using REST, facebookservice, facebook SDK. Where would these fit it?
Thanks
Sun
Ask for the publish stream permission.
You need to POST to https://graph.facebook.com/USER_ID/feed/access_token=lerolero, posting a json like this:
{"name": "name"
"link": "http://www.link.com/",
"caption": "title",
"description": "description",
"picture": "http://www.link.com/image.jpg"}
http://developers.facebook.com/docs/reference/api/, read the publishing section, you can send a lot of other information.
Edit:
I see two possibilities.
If the facebook integration its not part of your bussiness rules (if you will not use the user information), you can just add the SHARE widget, in this case, the user will se a button, and when he click the button, the facebook authentication page will open, and when the authentication is done, the share widget will popup automatically.
If you gonna access the user information (if will be somehow attached to the user account), then, when the user clicks the button, you have to check the user account forward a facebook account, if theres not one, you have to open a authentication popup, if the user succeeds to login into facebook, the authentication popup will return you a verification code. You must exchange the verication code for a access token and attach the access token to the user account in your database. In the authentication step, you have to ask for two special permissions, the stream publish permission and the offline access permission. The first one is about the resource to publish in the user wall, and the second one its about the access token life cycle (if you dont ask for this permission, the access token will have a short life cycle, and you will need to reauthenticate the user into facebook again and again, we dont want that).
Into the code:
When the user clicks a button, call a ajax function that checks if there's a access token in the user account. If theres, return the access token (take care here, if you create a ajax that return a access tokem based on a user id, you will have a very bad security issue), if theres not, return false.
If the code returned is false, call a function that opens a popup with the facebook authentication url. In the facebook authentication popup callback url, just exchange the verification code for a access token and store it in the database. You need to keep listening the popup.closed state, to know when the process is done and call another ajax function that checks if now theres a access token in the user account or not, if not, the user just closed the popup.
If the code returned is an access token, call a ajax function that post in the user wall, its very easy, like this:
string facebookurl = "https://graph.facebook.com/me/feed?access_token=32423"
string parameters = "message=aaaa&link=bbbb";
WebRequest req = WebRequest.Create(facebookurl);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(parameters);
req.ContentLength = bytes.Length;
Stream stream = req.GetRequestStream();
stream.Write(bytes, 0, bytes.Length);
stream.Close();
WebResponse res = req.GetResponse();
StreamReader streamReader = new StreamReader(res.GetResponseStream());
If you need any other piece of code, let me know.

Twitter's OAuth is asking my users to copy a PIN at sign in. Can I automate that step with Twitterizer?

I'm using Twitterizer. I got my Consumer key and Secret, and told Twitter my callback URL. However, after the user clicks permit, he gets a PIN to manually copy back to my application. I'm not even sure what I (the developer) am supposed to do with the PIN. Since the user isn't redirected back to the callback page, I'm not sure when that comes into play either.
I'm using the project template from 4 guys from Rolla. The callback page is internet visible (i.e. not just running on localhost)
protected string GetTwitterAuthorizationUrl()
{
string ConsumerKey = ConfigurationManager.AppSettings["ConsumerKey"];
string ConsumerSecret = ConfigurationManager.AppSettings["ConsumerSecret"];
OAuthTokenResponse reqToken = OAuthUtility.GetRequestToken(ConsumerKey, ConsumerSecret, "oob");
return "https://twitter.com/oauth/authorize?oauth_token=" + reqToken.Token;
}
Here is the corrected code:
string CallbackUrl2 = ConfigurationManager.AppSettings["CallbackUrl"];
OAuthTokenResponse reqToken = OAuthUtility.GetRequestToken(ConsumerKey, ConsumerSecret, CallbackUrl2);
return "https://twitter.com/oauth/authorize?oauth_token=" + reqToken.Token;
The reason the users are getting the PIN is because you have "oob" (out of browser) in your getrequesttoken call. Otherwise, they'd get a standard twitter authorization page asking if they want to authorize.

Resources