How do I post to an application's wall using Fb C# Sdk? - facebook

I've been trying to post something to my application's timeline/feed/wall on Fb, for the better part of the day but I keep failing. This is getting frustrating.
What I'm doing is : I'm having a simple console C# app, that is trying to post something on the application's wall (a basic hello world!, for instance).
This snippet shows how I'm retrieving an access token :
private string _AccessToken;
public string AccessToken
{
get
{
if (string.IsNullOrEmpty(_AccessToken))
{
//_AccessToken = string.Format("{0}|{1}", Credentials.AppId, Credentials.AppSecret);
Logger.Debug("Attempting to retrieve the access token...");
dynamic result = ExecuteGet("oauth/access_token", new
{
client_id = Credentials.AppId, // my app id
client_secret = Credentials.AppSecret, // my app secret
grant_type = "client_credentials",
scope = "manage_pages,publish_actions,publish_stream"
}, false);
_AccessToken = result.access_token;
}
Logger.Debug("Operation succeeded, access token is : {0}", _AccessToken);
return _AccessToken;
}
}
private object ExecuteGet(string path, object parameters)
{
return ExecuteGet(path, parameters, true);
}
private object ExecuteGet(string path, object parameters, bool useAccessToken)
{
try
{
Logger.Debug("Executing GET : {0}", path);
var client = useAccessToken ? new FacebookClient(AccessToken) : new FacebookClient();
return client.Get(path, parameters);
}
catch (FacebookApiException ex)
{
Logger.Error("GET Operation failed : {0}", ex.Message);
throw;
}
}
And this is how I'm trying to actually post something :
public void PostToApplicationWall(string message)
{
string path = string.Format("/{0}/feed", Credentials.AppId);
IDictionary<string, object> parameters = new Dictionary<string, object>()
{
{ "description", "[DESCRIPTION] Facebook description..." },
{ "link", "http://tinyurl.org" },
{ "name", "[NAME] Facebook name..." },
{ "caption", "[CAPTION] Facebook caption..." },
{ "message", message }
};
dynamic result = ExecutePost(path, parameters);
}
private object ExecutePost(string path, object parameters)
{
try
{
Logger.Debug("Executing POST : {0}", path);
var client = new FacebookClient(AccessToken);
return client.Post(path, parameters);
}
catch (FacebookApiException ex)
{
Logger.Error("POST Operation failed : {0}", ex.Message);
throw;
}
}
Please note that ExecutePost() uses the AccessToken property, I've pasted in the beginning.
The message that I'm getting is : (OAuthException - #210) (#210) Subject must be a page
Please help, I have no idea what am I doing wrong.

Maciek, if you really just want to post to your own page, writing a standalone app may not be the easiest way to do this. Have you tried PowerShell and http://facebookpsmodule.codeplex.com? This module will take care of the permissioning for you, and let you do this operation with a simple script.

App profile pages are discontinued since Feburary 1st 2012. You have to create an app page. Read here.
Now, when you have an app page, you change your code like this:
string path = string.Format("/{0}/feed", Credentials.PageId);
OR
string path = string.Format("/{0}/feed", Credentials.PageUsername);
[EDIT]
For posting to a page, you need the page access token instead of app access token. Read here on how to get a page access token.

Related

Box Java SDK Retrieve acces/refresh tokens

I am trying to create a java program that will search for certain files in Box Storage. For this i am trying to use the Box Java SDK and i created an application in Box (https://app.box.com/developers/services).
When i use the developer token i am able to traverse through my box parent/child folders. Since this token is valid for 60 mins i want to programmatically retrieve and set the token. When i looked at the manuals it says to manully call api's to get these tokens.
I tried the below code..
BoxAPIConnection api = new BoxAPIConnection(clientid,clientsecret);
String accesstoken = api.getAccessToken();
String refreshtoken = api.getRefreshToken();
I dont want to throw a box login page to the user and want to run this program as a daemon which will search files and spit out some report text file.
Thanks for all the help.
It is possible to manage Box login through code.
For the first time you access Box.com and get the client id, client secret, access token and refresh token.
Save it in DB or property file.
Use below code, and each and every time update the actual access and refresh token.
String accessToken = // access token from DB/property
String refreshToken = // refresh token from DB/property
String boxClientId = // client id from DB/property
String boxClientSecret = // client secret from DB/property
try {
BoxAPIConnection api = new BoxAPIConnection(boxClientId, boxClientSecret, accessToken, refreshToken);
api.addListener(new BoxAPIConnectionListener() {
#Override
public void onRefresh(BoxAPIConnection api) {
String newAccessToken = api.getAccessToken();
String newrefreshToken = api.getRefreshToken();
// update new access and refresh token in DB/property
}
#Override
public void onError(BoxAPIConnection api, BoxAPIException error) {
LOGGER.error("Error in Box account details. " + error.getMessage());
}
});
LOGGER.debug("Completed Box authentication");
} catch (Exception e) {
LOGGER.error("Error in Box authentication. Error msg : " + e.getMessage());
}
If you use a state.conf file, you'll be able to refresh the token/refres_token pair programmatically without getting an auth code. Here's a code snippet that I use:
private static BoxAPIConnection getBoxAPIConnection(String client_id, String client_secret, String token, String refresh_token, String stateConfPath) {
String state = null;
try {
logger.info("Getting state.conf: " + stateConfPath + "/state.conf");
InputStream fis = new FileInputStream(stateConfPath + "/state.conf");
InputStreamReader isr = new InputStreamReader(fis, Charset.forName("UTF-8"));
BufferedReader br = new BufferedReader(isr);
state = br.readLine();
}
catch (FileNotFoundException f) {
try {
// create file if it doesn't exist
PrintWriter writer = new PrintWriter(stateConfPath + "/state.conf", "UTF-8");
writer.println("");
writer.close();
}
catch (Exception w) {
logger.fatal("Exception", w);
}
}
catch (IOException e) {
logger.fatal("IOException", e);
}
BoxAPIConnection api = null;
//if (null == state || "".equals(state)) {
if (!token.equals("") && !refresh_token.equals("")) {
api = new BoxAPIConnection(client_id, client_secret, token, refresh_token);
} else {
logger.info("Restoring state..." + state);
api = BoxAPIConnection.restore(client_id, client_secret, state);
if (api.needsRefresh()) { // this is not a reliable call. It can still throw a 401 below
logger.info("api refreshing...");
api.refresh();
}
else {
logger.info("api good...");
}
}
return api;
}

Post to group wall using Facebook SDK .net 2015

It seems that nowdays there's no way to allow to post onto facebook user groups via a new, unreviewed app.
I've created an App with live features availible to gen public, with approvements for email, public_profile, user_friends.
I'm trying to post on the wall of a group I've created and I'm an admin of.
Now, when firing up my code, I get the nasty "OAuthException - #200) (#200) Insufficient permission to post to target..." exception.
Posting my wall work perfectly...
public class HomeController : Controller
{
private const long GroupId = 15473890820xxxx;
//
// GET: /Home/
public ActionResult Index(string code)
{
ViewBag.Message = "Welcome to Facebook App Demo!";
//user denied permissions on Facebook.
if (Request["error_reason"] == "user_denied")
{
//this is not implemented. For reference only.
return RedirectToAction("LogOn", "Account");
}
if (string.IsNullOrEmpty(code))
{
ViewBag.Error = "There was an error while loggin into Facebook. Please try again later.";
return RedirectToAction("LogOn", "Account");
}
var fb = new FacebookClient();
dynamic result = fb.Post("oauth/access_token", new
{
client_id = "93199615018xxxx",
client_secret = "2089ae4447877e7388500b844235xxxx",
redirect_uri = "http://localhost:13301/",
code = code
});
var appToken = result.access_token as string;
// update the facebook client with the access token so
// we can make requests on behalf of the user
fb.AccessToken = appToken;
//get extended App/User Token
dynamic result2 = fb.Get("oauth/access_token", new
{
client_id = "93199615018xxxx"
client_secret = "2089ae4447877e7388500b844235xxxx",
grant_type="fb_exchange_token",
fb_exchange_token = appToken,
// code = code
});
var extendedAppToken = result2.access_token as string;
//generate Extended User Token (valid for 60 days)
Session["Facebooktoken"] = extendedAppToken;
dynamic me = fb.Get("me/accounts");
var response = fb.Get("/me/accounts?access_token=" + extendedAppToken) as JsonObject;
return View(me);
}
[HttpPost]
public ActionResult Index(FormCollection collection) //rename to PostWall
{
ViewBag.Message = "Welcome to Facebook App Demo!";
// Post to the wall..
try
{
if (Session["Facebooktoken"] != null)
{
string message = collection["txtPost"].ToString();
FacebookClient client = new FacebookClient(Session["Facebooktoken"].ToString());
dynamic result = client.Post(GroupId+"/feed", new
{
message = message
});
ViewBag.SaveMessage = "Successfuly Post on your wall : " + result.id;
}
else
{
return RedirectToAction("LogOn", "Account");
}
}
catch (Exception ex)
{
ModelState.AddModelError("", ex.Message);
}
return View();
}
public ActionResult About()
{
return View();
}
}
public class AccountController : Controller
{
//
// GET: /Account/
public ActionResult LogOn()
{
return View();
}
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
var facebookAppId = "93199615018xxxx";
var facebookAppSecret = "2089ae4447877e7388500b844235xxxx";
var facebookRedirectUrl = "http://localhost:13301/";
//
var facebookScope = "email,publish_pages,publish_actions,manage_pages,user_managed_groups,user_hometown,user_website";
if (facebookAppId != null && facebookAppSecret != null && facebookRedirectUrl != null && facebookScope != null)
{
var url = string.Format(#"https://www.facebook.com/dialog/oauth/?client_id={0}&redirect_uri={1}&scope={2}", facebookAppId, facebookRedirectUrl, facebookScope);
Response.Redirect(url, true);
}
return this.RedirectToAction("Index", "Home");
}
}
Any clue on how to set up an testing environment for above functionality without the extra-round of establishing a fully fledged App that has to be reviewed by Facebook admins? I've looked on testing versions for Apps and Users, but no groups either.
Many thanks in advance
Darren, thanks for your considerations. It seems like due to my privacy restrictions I couldnt get any group info of my personal account. Either programmatically, nor manually in Facebooks Graph API Explorer.
It worked finally on an business (fan)'Page' profile by getting an 'long-lived' Page Access Token in facebooks Access Token Debuger.
Yes, user_managed_groups and publish_actions had been enabled.

Google API consent screen not showing up on after publishing to server

I am working with the Google Provisioning API. I have used Web Application type project from Google developer console. I have used Diamto blog and samples and it works perfectly on my local with all options like FileStore, Custom File Store, Service Account etc but when I uploaded on server user consent screen just doesn't pops up with any options like FileStore, Custom File Store. I spent days to figure out problem and solutions but nothing has worked for me so far.
my configuration
My server configuration is windows server 2008 datacenter r2,.net 4.5,IIS 7.5.
Service account works perfectly but I need to do it by Consent screen so Web Application type of project.
I have used google .net client library with version 1.9.2.27817.
I am just highlighting main code where it gets stuck and rest is same as per Diamto post and github examples.
Let me know if you need more info.
Code
public static DirectoryService AuthenticateOauth(string clientId, string clientSecret, string userName, IDataStore datastore)
{
string[] scopes = new string[] {DirectoryService.Scope.AdminDirectoryUser };
try
{
// here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }
, scopes
, userName
, CancellationToken.None
, datastore).Result; // at this point it calls getasynch method for custom datasource
DirectoryService service = new DirectoryService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "GoogleProv",
});
return service;
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
return null;
}
}
{
HttpClientInitializer = credential,
ApplicationName = "GoogleProv",
});
return service;
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
return null;
}
}
///<summary>
// Returns the stored value for the given key or <c>null</c> if the matching file (<see cref="GenerateStoredKey"/>
// in <see cref="FolderPath"/> doesn't exist.
// </summary>
// <typeparam name="T">The type to retrieve</typeparam>
// <param name="key">The key to retrieve from the data store</param>
// <returns>The stored object</returns>
public Task<T> GetAsync<T>(string key)
{
//Key is the user string sent with AuthorizeAsync
if (string.IsNullOrEmpty(key))
{
throw new ArgumentException("Key MUST have a value");
}
TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
// Note: create a method for opening the connection.
SqlConnection myConnection = new SqlConnection(myconn);
myConnection.Open();
// Try and find the Row in the DB.
using (SqlCommand command = new SqlCommand("select RefreshToken from GoogleUser where UserName = #username;", myConnection))
{
command.Parameters.AddWithValue("#username", key);
string RefreshToken = null;
SqlDataReader myReader = command.ExecuteReader();
while (myReader.Read())
{
RefreshToken = myReader["RefreshToken"].ToString();
}
if (RefreshToken == null )
{
// we don't have a record so we request it of the user.
tcs.SetResult(default(T)); // it comes here
}
else
{
try
{
// we have it we use that.
tcs.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize<T>(RefreshToken));
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
}
return tcs.Task; // it comes here and than gets hang forever
}
Any of your help is highly appreciated.

Error using facebook C# sdk with WPF web browser

I am new to facebook c# sdk. I followed the tutorial in this link.
I created an application that displays the user name after log in. Here is my code:
public partial class MainWindow : Window
{
private string appId = "appid";
private string extenededPermissions = "offline_access,publish_stream";
private Uri loginUrl = null;
private string accessToken = null;
private string userName = null;
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// Function to get the login url
/// with the requested permissions
/// </summary>
private void GetLoginUrl()
{
dynamic parameters = new ExpandoObject();
// add the client id
parameters.client_id = appId;
// add the redirect uri
parameters.redirect_uri = "https://www.facebook.com/connect/login_success.html";
// requested response
parameters.response_type = "token";
// type of display
parameters.display = "popup";
// If extended permissions are present
if (!string.IsNullOrWhiteSpace(extenededPermissions))
parameters.scope = extenededPermissions;
// Create the login url
Facebook fc = new FacebookClient();
loginUrl = fc.GetLoginUrl(parameters);
}
private void WindowLoaded(object sender, RoutedEventArgs e)
{
// get the login url
GetLoginUrl();
// Navigate to that page
webBrowser.Navigate(loginUrl);
}
private void webBrowser_Navigated(object sender, NavigationEventArgs e)
{
var fc = new FacebookClient();
FacebookOAuthResult fr;
// Check the returned url
if (fc.TryParseOAuthCallbackUrl(e.Uri, out fr))
{
// check if authentication is success or not
if (fr.IsSuccess)
{
getUserName(out userName);
}
else
{
var errorDes = fr.ErrorDescription;
var errorReason = fr.ErrorReason;
}
}
else
{
}
}
private void getUserName(out string name)
{
var fb = new FacebookClient(accessToken);
// Get the user details
dynamic result = fb.Get("me");
// Get the user name
name = result.name;
MessageBox.Show("Hai " + name + ",Welcome to my App");
}
}
My Problem is with the FacebookOAuthResult.
private void webBrowser_Navigated(object sender, NavigationEventArgs e)
{
var fc = new FacebookClient();
FacebookOAuthResult fr;
// Check the returned url
if (fc.TryParseOAuthCallbackUrl(e.Uri, out fr))
{
// check if authentication is success or not
if (fr.IsSuccess)
{
getUserName(out userName);
}
else
{
var errorDes = fr.ErrorDescription;
var errorReason = fr.ErrorReason;
}
}
else
{
}
}
After I logged in it is redirecting to redirect_uri. But the fc.TryParseOAuthCallbackUrl(e.Uri, out fr) fails though the webbrowser redirects to the Authentication successful page.
So I couldn't get the access token. What could the problem in my code be?
This doesn't answer the question, but I see you are asking for an offline_access permission. Facebook removed offline_access sometime ago. Instead you need an Extended Access Token. You get it by exchanging the access token you are trying to get, for an extended one. They last for about 2-3 months after which you have to get a new one.
Nevermind i have found out the solution..Thanks to the answers for the question!
I have added the Winforms web browser control to the wpf and the authentication is working.The problem is with WPF web browser. It simply omits the url after # token So the parseurl won't able to authenticate it.
Here's the modified code..
private void WindowLoaded(object sender, RoutedEventArgs e)
{
// create the windows form host
System.Windows.Forms.Integration.WindowsFormsHost sample =
new System.Windows.Forms.Integration.WindowsFormsHost();
// create a new web browser
webBrowser = new System.Windows.Forms.WebBrowser();
// add it to winforms
sample.Child = webBrowser;
// add it to wpf
canvas1.Children.Add(sample);
webBrowser.Navigated += webBrowser_Navigated;
webBrowser.Navigate(loginURL);
}
void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
// do the authentication
var fc = new FacebookClient();
FacebookOAuthResult fr;
// Check the returned url
if (fc.TryParseOAuthCallbackUrl(e.Url, out fr))
{
// check if authentication is success or not
if (fr.IsSuccess)
{
accessToken = fr.AccessToken;
// Actions to do
}
else
{
var errordes = fr.ErrorDescription;
var errorreason = fr.ErrorReason;
}
}
else
{
//Not a valid url
}
}
The problem is solved!!

DotNetOpenAuth Claimed Identifier from Facebook is never the same

I'm using DotNetOpenAuth v3.5.0.10357 and each time a user authenticates against Facebook I get a different claimed identifier back. The token looks to be encrypted so I assume DNOA is somehow encrypting the token along with the expiry. Can anyone confirm this? Or am I using it wrong:
public ActionResult FacebookLogOn(string returnUrl)
{
IAuthorizationState authorization = m_FacebookClient.ProcessUserAuthorization();
if (authorization == null)
{
// Kick off authorization request
return new FacebookAuthenticationResult(m_FacebookClient, returnUrl);
}
else
{
// TODO: can we check response status codes to see if request was successful?
var baseTokenUrl = "https://graph.facebook.com/me?access_token=";
var requestUrl = String.Format("{0}{1}", baseTokenUrl, Uri.EscapeDataString(authorization.AccessToken));
var claimedIdentifier = String.Format("{0}{1}", baseTokenUrl, authorization.AccessToken.Split('|')[0]);
var request = WebRequest.Create(requestUrl);
using (var response = request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
var graph = FacebookGraph.Deserialize(responseStream);
var token = RelyingPartyLogic.User.ProcessUserLogin(graph, claimedIdentifier);
this.FormsAuth.SignIn(token.ClaimedIdentifier, false);
}
}
return RedirectAfterLogin(returnUrl);
}
}
Here's the code for FacebookAuthenticationResult:
public class FacebookAuthenticationResult : ActionResult
{
private FacebookClient m_Client;
private OutgoingWebResponse m_Response;
public FacebookAuthenticationResult(FacebookClient client, string returnUrl)
{
m_Client = client;
var authorizationState = new AuthorizationState(new String[] { "email" });
if (!String.IsNullOrEmpty(returnUrl))
{
var currentUri = HttpContext.Current.Request.Url;
var path = HttpUtility.UrlDecode(returnUrl);
authorizationState.Callback = new Uri(String.Format("{0}?returnUrl={1}", currentUri.AbsoluteUri, path));
}
m_Response = m_Client.PrepareRequestUserAuthorization(authorizationState);
}
public FacebookAuthenticationResult(FacebookClient client) : this(client, null) { }
public override void ExecuteResult(ControllerContext context)
{
m_Response.Send();
}
}
Also, I am using the RelyingPartyLogic project included in the DNOA samples, but I added an overload for ProcessUserLogin that's specific to facebook:
public static AuthenticationToken ProcessUserLogin(FacebookGraph claim, string claimedIdentifier)
{
string name = claim.Name;
string email = claim.Email;
if (String.IsNullOrEmpty(name))
name = String.Format("{0} {1}", claim.FirstName, claim.LastName).TrimEnd();
return ProcessUserLogin(claimedIdentifier, "http://facebook.com", email, name, claim.Verified);
}
It looks as though FacebookClient inherits from WebServerClient but I looked for the source on GitHub and I don't see a branch or a tag related (or at least not labeled) with the corresponding v3.5 version.
Facebook does not support OpenID. Claimed Identifier is an OpenID term. Facebook uses OAuth 2.0, so you're mixing up OpenID and OAuth.
Facebook sends a different access token every time, which is normal for the OAuth protocol. You have to use the access token to query Facebook for the user id that is consistent on every visit.
I think you need to add the offline_access permission in the token request as well, see https://developers.facebook.com/docs/reference/api/permissions/