Facebook signed_request validates but no data in decoded payload: C# - c#

Folks, would really appreciate your help on this as maybe I'm just missing something really obvious. Basically, i'm trying to develop a Facebook canvas iframe app in C# ASP.NET that a business can install on a fan page and users can access via a tab.
Main Requirements:
1. Business clicks install which takes them to apps.facebook.com/myapp
2. I needs to check if I have record in database for that Facebook Profile
3. N: Display page where business enters a unique code. Save Profile Id and Code
4. Y: Display data from database related to that business.
The Issue:
I've created app in Facebook and created an ASP.NET website with a single page. The app is running on my dev machine under IIS. When I visit the app on Facebook, it hits my page. I retrieve and validate the signed_request with my API key. However, the decoded payload contains only the SHA256 parameter and no user, oauth, or profile data.
Is there something else I need to do or is my approach completely incorrect?
Appreciate any guidance on this.

Are you requiring user auth, doing the full handshake?
Have you enabled the "OAuth 2.0 for Canvas (beta)" migration in your Facebook app? It's the last tab of your app config.

If the user visiting your iframe inside the canvas page has not authorized your app, the payload inside the signed_request will be something like this:
{
"algorithm":"HMAC-SHA256",
"issued_at":1286824906
}
On the other hand, if your user has authorized your app, the payload inside the signed_request will be something like this:
{
"algorithm":"HMAC-SHA256",
"expires":1286827200,
"issued_at":1286821560,
"oauth_token":"Some Token",
"user_id":"Some ID"
}
Because you're missing the user_id inside the payload, it sounds like the user has not yet authorized your app.

Related

ASP.NET C# Get Facebook user details

I start to working with the Facebook graph API and I have question:
I make Facebook Authentication, so after user approve my application I got accessToken and the facebookUserID. note: The accessToken is expire after One hour(!!!).
Then, in another webpage "index.html", I want to show all the users who approved the application with their full name and profile picture taken from Facebook.
Now I don't understand.. if someone will enter the "index.html" page to see list of users who accepted the application - 5(!!) month after their authentication, when i will make the HTTP call to get thier fullname and profile picture, the accessToken is now expire(a lot time before) so the HTTP call will not succeed.
The last option is to save the full name just in the One hour between user accept the application and before the accesstoken expiration. but if the user will change his name sometime... I don't have the updated Name!
if its important - I'm usind the javascriptSDK with asp.net project.
Please help me to understand how to solve this situation.
It would appear that it is not possible to generate a long-lived token with the JS SDK directly, you will have to involve the server side, see this page for details.

DropNet DropBox login, how to do it programmatically in a console application?

Question:
I'm using a DropBox csharp API from here:
https://github.com/dkarzon/DropNet
From the Unit tests, and the only working sample from here
https://github.com/dkarzon/DropNet/blob/master/DropNet.Samples/DropNet.Samples.Web/Default.aspx.cs
I figured that it works like this:
DropNet.DropNetClient client = new DropNet.DropNetClient(strApiKey, strAppSecret);
DropNet.Models.UserLogin login = client.GetToken();
client.UserLogin = login;
var accountInfo = client.AccountInfo();
str = accountInfo.quota_info.quota.ToString();
The probem is, it throws an exception on accountinfo. (System.Net.HttpStatusCode.Unauthorized)
Everything before works fine, I get the login (usertoken & usersecret) .
I think my problem is this part of the sample application:
var url = _client.BuildAuthorizeUrl(Request.Url.ToString() + "?dropboxcallback=1");
Response.Redirect(url);
Where it redirects to dropbox for a login...
I don't have a web application, so I have no URL...
What I have is a console application, that should make a backup of my database every evening automatically as a service, for which it certainly is very bad requiring a webbrowser and a user which has to type in email/username + password.
How can I do a login by directly supplying the hardcoded username and password ?
If I use the sample application, then it works, but that requires typing in the username and password on the web, and that sucks big time for a console application...
As far as I know from other API's (facebook, google, stack exchange etc.) you'll have to redirect your user to a webpage of Dropbox, where it will grant permissions to you to use it's account to perform things.
So in general it is not possible to achive this without a webbrower. Otherwise you'll have to perform really dirty hacks to hack arround the permission system of dropbox.
Please have a look at "OAuth 2.0 authorization flow" on google.
Here's a diagram I found at Yahoo which show's how it works:
For uisng the DropnetClient's 4 argument constructor also we need to build web based url and allow the user to authenticate his account this is compusory thing, accesstoken will generate after the user hit allow button in authentication process
As GameScripting explained the Dropbox API uses oauth which requires user login through the dropbox website to authenticate the access tokens.
Checkout the documentation here: http://dkdevelopment.net/what-im-doing/dropnet/ for the 3 step process.
What sort of application are you building? Normal process is to load a browser control inside the application and navigate to the login URL with it.
Also have a look at the sample Windows Phone app to give you an idea of how this process works: https://github.com/dkarzon/DropNet/blob/master/DropNet.Samples/DropNet.Samples.WP7/MainPage.xaml.cs
Instead of hardcoding the username and password, you can hardcode the OAuth access token.
First, create a simple program (using the same app key) that follows the standard browser-based authorization flow. Then use it to authorize the app with the desired user. This will give you an OAuth access token (a "token" and "token secret") associated with that user and your app key.
Then, in your service-style application, just hardcode the OAuth access token (using DropNetClient's 4-argument constructor).
It is possible, using SharpBox - tested, works.
One needs to acquire the AccessToken as a one-time-action manually, then after that, one can omit the login page and use the saved AccessToken.
http://www.jayway.com/2012/02/06/unboxing-dropbox-and-sharpbox-2/
The magic line is:
Globals.DropBox.Token = AppLimit.CloudComputing.SharpBox.StorageProvider.DropBox.DropBoxStorageProviderTools
.ExchangeDropBoxRequestTokenIntoAccessToken(
Globals.DropBox.config
, Globals.DropBox.AppKey, Globals.DropBox.AppSec
, Globals.DropBox.requestToken
);

MVC3 + How to get the current logged on user's user name

I am new to MVC and actually new to web development all together. I have about 7 years of development experience but in services, database, object models, etc.. basically middle-tier and back-end development. I am trying to learn ASP.NET and decided to build a site using MVC3 for a personal site for myself. I will be hosting this from an account at dotnet-hosts.com. Here is my question... I don't have a domain and I will be using the built in membership provider. I noticed in the auto generated code that was created when I added the project template that in the AccountController in the method ChangePassword (ChangePasswordModel model) there is this line of code...
MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
My question is specifically around User.Identity.Name, this looks like it would be returning the Windows user name just like Environment.UserName would. The Visual Studio template I used is the (Mobile Ready HTML5 MVC.NET) as I want to be able to support clients from any device...Windows PC, Apple, Windows Phone, iPhone, etc... If the call to User.Identity.Name is correct then I would like to ask how does this work on devices that are not Windows like an iPhone? If my assumption is correct that this will only work for Windows computers with a domain then how can I achieve this? would I need to perhaps use some caching? If so could I maybe grab the user name and their IP address to be used as the cache key from the Authentication page?
My high level question is... How do I get the current logged in user's userName regardless of the device/platform? I know this question is probably not written well and may be hard to understand... I apologize for that. I am new to web development and trying to get my feet wet and would like to start to the latest technology.
The call is correct. The User.Identity.Name is filled out by whatever authentication provider is in use - Windows authentication, Forms authentication, some custom authentication provider, or whatever. It isn't bound to a specific user "type". The authentication provider has the responsibility of making sure the Identity object corresponds to the current user on every request. Usually that part is taken care of using a combination of cookies and database.
The MVC template (although I haven't had a look at the template since MVC 2) uses ASP.NET's Membership class, which in turn uses a membership provider - for example SqlMembershipProvider or ActiveDirectoryMembershipProvider - the former stores your users' credentials (username and password etc.) in an SQL Server database, the latter uses Active Directory (i.e. primarily Windows logons). SqlMembershipProvider is the default, and MVC is set up to use a local SQLExpress database file as its user store.
The authentication provider that's implemented in the template project uses FormsAuthentication, which does the login procedure through a simple HTML form (the one in the LogOn view) and keeps the user signed in by way of an encrypted cookie. Works on any platform.
The setup for both FormsAuthentication and SqlMembershipProvider can be found in web.config (the one in the root of the site). There you can find the connection strings for the SQLExpress database (and e.g. change them to use a "real" SQL Server if needed), the timeout for logins etc.
(Note that you can do a lot of that configuration easily in a GUI through the "ASP.NET Configuration" button in the toolbar of Solution Explorer in Visual Studio - it also provides an easy way to set up the first users).
In short, it's all ready to go - and doesn't lock out non-Windows users.
Like you said User.Identity.Name is indeed correct. for returning the logged in users name. But the membership section like you said, provides only windows accounts. You can use similar without the user of windows accounts, to work in every scenario, and can still verify against windows if present. If you call it without membership, and follow the default MVC3 template it should work fine.
String Username = User.Identity.Name;
When you log on, using the template MVC3, it creates an authcookie. See account controller code. Here, two parameters are passed into it. The username, and to persist (when browser is closed - login is still cached).
The username is a string field, which is what is called by User.Identity.Name and infact, anything can be put into it, and is not in anyway linked to Windows login.
You could test the login via method you desire, and if yes, set a cookie using the authcookie method. (its encripted). And set the username to what ever you want. And if your verification of the user fails, dont create one, and redrect back to page.
See the example code. This is all from memory, as I dont have code infront of me for reference. But its all in the account controller, Login Action.
When the cookie is set, The users login state is cached for the session. You will need to ensure the user is logged in when visiting a webpage. Otherwise loggin in will be pointless. This is a simple attribute on the controller/action.
Note: dont do this to the Account/logon controller, as you wont be able to visit the logon page, as you are not logged in.
[Authorize]
public ActionResult DoSomething()
{
// ...
}
Hope I have helped.

Facebook Authentication c# integration using Facebook login buttons

I have created an application that logs in and registers via a button click. This all works as expected by using the access token in the code behind to process the login and gain users details for prefilling some forms.
The customer has now asked for something similar to the facebook login button that puts the login/ application authentication in like a frame, rather than redirecting the user to facebook.
Looking at the documentation I am a bit puzzled on how to do this. Do the facebook login/authentication javascript buttons provide an access code for manipulation in the code behind.
Have you considered a popup login using the Facebook javascript SDK like so:
FB.ui({ method: 'auth.login',
perms: 'publish_stream',
display: 'popup' },
function (rsp) {
fg_log('on login');
if(rsp.session) {
if(rsp.perms) {
} else {
}
} else {
fg_log('No login');
}
}
);
http://developers.facebook.com/docs/reference/javascript/FB.ui/
http://developers.facebook.com/docs/reference/javascript/
The Social Plugins are self contained, and do everything client-side. You can however hook the login/logout events in the JavaScript SDK and use AJAX to talk to the server. You can also get the Facebook auth cookie server-side on subsequent requests to see if the user is logged in, which can also be validated.
Take a look Integration of Facebook and asp.net membership, for an example of setting up .Net authentication with Facebook access_token.
Basic approach that I took for my own projects are:
use facebook javascript SDK to do user login.
after login is successful, user will be able to grand their
access_token
Pass that access_token in your postback page query string (or anything suits you)
by using Graph API with Access_token from code behind you will be
able to grab user info from facebook.
then you will able to compare user info between your own user
provider and set that user as logged in

Questions about the facebook SDK

I am looking at using the facebook SDK and I am wondering first what version should I be using?
It looks like some major changes are happened from 4.2 to 5(currently still in beta). Should I go ahead and use the beta? Anyone have any ides when it will be out of beta?
My second question is how can I use it for authentication.
Right now I am using DotNetOpenAuth to do all my openId authentication for my site. I am using there sort of plugin for facebook authentication(oAuth) however I am planning to use more facebook features on my site so I think it is kinda pointless to use this plugin and then the sdk libary when the library seems to be able to do it all.
Anways how do I do authentication with the sdk library. I want to have a button on my login page that they click it goes off to facebook they become authenticated and I get some request back saying that they where authenticated and then I give them a cookie and let them in.
All the tutorials I seen to have it that your just using facebook as your only authentication method but of course for me I have openId, facebook and twitter.
http://facebooksdk.codeplex.com/wikipage?title=Getting%20Started%20with%20an%20ASP.NET%20MVC%203%20Website&referringTitle=Getting%20Started
I use the Facebook SDK, and my advice for you would be to use the beta
The reason is because Facebook is changing and depreciating a lot of the Old REST interface and making Graph API the only way to access data. So, to be future proof, the latest and greatest is the way to go.
Now, it is a beta, so everything isn't 100%. If you need stability and don't mind making changes, then use the stable version and then upgrade later.
As for authentication, the process to authenticate is pretty simple.
you need your authURL:
string authURL = #"https://graph.facebook.com/oauth/authorize?client_id=" + Settings.appId + "&redirect_uri=" + redirectUrl + permissions
where appId is your Facebook Application ID (you get it when you register your app with Facebook), the redirectUrl is the URL that you want Facebook to send you the challenge token, and your permissions are the list of things you want to access with your Facebook authentication Token
You make a popup or whatever that browses to that URL. The user will login to facebook (if they haven't already) and then they will be presented with the app authorization screen (if they haven't already authorized the app). Once they authorize (or imidiately if they already authorized), the page will be forwarded to the redirectUrl that you provided. In the URL, there will be a GET variable called code that will contain the challenge string. You take that challenge code and add it as a query variable to another URL that is in the form of:
https://graph.facebook.com/oauth/access_token?client_id=YOURID&redirect_uri=http://www.facebook.com/connect/login_success.html&client_secret=YOURSECRET&code=THATCODE
That URL will return the authentication key...
Phew! That's quite the process.... If done manually :) Now that you know a little more about what's going on, you can appreciate what the SDK does for you.
To authenticate with the SDK, Just follow the 19 simple steps as outlined in this link
Easy huh?
Regarding 4.2 vs 5.0 BETA I guess you need to decide whether you want to use a BETA version or a stable version. I am sure they have a changelog in their BETA Release you can look at for the changes since the older version.
Regarding authentication using Facebook. I have a project where I support standard Forms authentication and accounts creation as well as Facebook login. In my AccountController I have one action for Forms login and one for Facebook login.
To configure the Facebook assembly you can follow the tutorial you have posted, then you can put a Facebook button on your page and similar code to begin the authentication process:
<script type="text/javascript" src="http://connect.facebook.net/en_US/all.js"></script>
<script type="text/javascript">
$(function () {
FB.init({ appId: '<%= FacebookSettings.Current.AppId %>', status: true, cookie: true, xfbml: true });
$('#fbLoginButton').click(function () {
FB.login(function (response) {
if (response.session) {
// Success - execute our facebook login action.
window.location = "<%= Url.Action("FacebookLogin", "Account") %>";
} else {
// user cancelled login or failed
}
}, { perms: 'email' });
return false;
});
});
The facebook aciton works by:
Was Facebook Authentication successful?
Do we have a user with the Facebook Id as a username in the system?
If not create a user, populate name, email, etc from the Facebook data
Set the Forms authentication cookie
Pseudo code:
FacebookApp facebook = new FacebookApp ();
if (facebook.IsAuthenticated) {
string userName = facebook.UserId.ToString();
if (UsersRepository.ByUserName(userName ) == null) {
// Create a User using the Facebook name, email, etc data
}
FormsAuthentication.SetAuthCookie (userName , true);
}
So the idea is that I delegate the authentication to those 3rd party services and then create a user on my system with the information I can fetch from them. Also in my project, because I want the user to set/very some preferences after the account is created I redirect them to the page where they can do that.
P.S: A tip regarding running your web project locally in Visual Studio. You can create a private Facebook App with "Site URL" set to e.g. "http://localhost:4911/" and use that appId. This will allow you to play with Facebook locally.

Categories

Resources