问题
I have an MVC5 app and have figured out how to authenticate with facebook initially using Identity 2.0. Other than adding email to the scope, it is basically default:
var options = new FacebookAuthenticationOptions()
{
AppId = "##################",
AppSecret = "######################"
};
options.Scope.Add("email");
app.UseFacebookAuthentication(options);
In another section of my app, it is possible that the user would need to upgrade the facebook token to be able to publish to their wall as well (I was hoping to just add options.Scope.Add("publish_stream");
). When I cut the above code out and place it inside the catch
here (the code below is referenced here at facebooksdk.net):
try {
var client = new FacebookClient("my_access_token");
dynamic result = client.Get("me/friends");
} catch (FacebookOAuthException) {
// Our access token is invalid or expired
// Here we need to do something to handle this.
}
It doesn't like the app.
for starters and I can't figure out what to replace that with. What is the correct way to go about this? I realize there are examples on facebooksdk.net for whatever token request they do, but I was hoping to integrate it with Identity 2.0. Or does it matter? I'm not sure I'm understanding the Identity process correctly and not really familiar with facebook authentication either, so hopefully someone can understand what I'm trying to do and guide me? My guess would be that I simply need to pass my facebook token in the Logins SQL table to facebook where it would ask the user to reauthenticate with the elevated permissions? If the token doesn't initially exist in the Logins table, the process will add it there.
For the record, I realize I can request the permissions initially (when the user logs in to our site with facebook for the first time), but we're trying not to scare off the more savvy users initially. So, the idea would be when they click to publish their article, if they opt to publish to facebook, it will then request the upgrade of the token the first time and then hopefully never again (which the never part may be wishful thinking).
Thank you.
回答1:
Facebook can be confusing. The token you need depends on the action you are trying to achieve. For instance,
- You use your app token to request a user token that has specific permissions.
- You would then use that USER TOKEN to access the facebook api on behalf of the user.
In the code you posted, it appears you have the access token that you are sending to facebook to be the access token granted to your app ... not the given user's access token. You need to capture (and store) the user's access token given to you by facebook after having successfully been granted access for a given user. More on this here: https://developers.facebook.com/docs/facebook-login/access-tokens
Here is some sample code (used in startup_auth.cs) that uses the Identity framework. It captures the access token and persists it (as a claim) for a given user. The access token can be read later for access to the facebook api for a user at any given time.
// Facebook integration
var facebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions()
{
AppId = ConfigurationManager.AppSettings["Facebook.appID"],
AppSecret = ConfigurationManager.AppSettings["Facebook.appSecret"],
Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider()
{
OnAuthenticated = (context) =>
{
// STORE THE USER ACCESS TOKEN GIVEN TO US BY FACEBOOK FOR THIS USER
context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, XmlSchemaString, "Facebook"));
foreach (var x in context.User)
{
var claimType = string.Format("urn:facebook:{0}", x.Key);
string claimValue = x.Value.ToString();
if (!context.Identity.HasClaim(claimType, claimValue))
context.Identity.AddClaim(new Claim(claimType, claimValue, XmlSchemaString, "Facebook"));
}
return Task.FromResult(0);
}
}
};
facebookOptions.Scope.Add("email");
facebookOptions.Scope.Add("publish_actions");
app.UseFacebookAuthentication(facebookOptions);
So now to retrieve the access token FOR THE USER, you would retrieve it (in the callback function/url from facebook) like this:
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
var accessToken = loginInfo.ExternalIdentity.Claims
.Where(c => c.Type.EndsWith("facebook:access_token"))
.FirstOrDefault();
....
}
来源:https://stackoverflow.com/questions/31280580/integrate-facebooksdk-with-identity-2-0