I've just developed my first c# app to post on facebook. Currently, I have no problems to post on my wall, but what I want to do is to post on group's wall, but not as admin, but as regular user. When I changed ID to post with group one instead of my profile, I get auth error. It seems I am missing some permissions. Please take a look at my code and tell me what I am missing to post on given group's wall, and again to underline, I want to post as regular user of the group, not as admin.
So I use this when I am getting the permissions.
private const string ExtendedPermissionsNeeded = "publish_actions";
I am using this to generate Login Url
private string GenerateLoginUrl()
{
dynamic parameters = new ExpandoObject();
parameters.client_id = app_id;
parameters.redirect_uri = "https://www.facebook.com/connect/login_success.html";
parameters.response_type = "token";
parameters.display = "popup";
if (!string.IsNullOrWhiteSpace(ExtendedPermissionsNeeded))
parameters.scope = ExtendedPermissionsNeeded;
var fb = new FacebookClient();
Uri loginUri = fb.GetLoginUrl(parameters);
return loginUri.AbsoluteUri;
}
And finally here is what i am using to post on facebook:
private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
string accessToken;
bool authorized;
if (webBrowser1.Visible)
{
var fb = new FacebookClient();
FacebookOAuthResult oauthResult;
if (fb.TryParseOAuthCallbackUrl(e.Url, out oauthResult))
{
if (oauthResult.IsSuccess)
{
accessToken = oauthResult.AccessToken;
authorized = true;
}
else
{
accessToken = "";
authorized = false;
}
if (authorized)
{
fb = new FacebookClient(accessToken);
dynamic result = fb.Get("me");
fb.Post("/100000853192437/feed", new { message = "test " });
}
else
{
MessageBox.Show("Couldn't log into Facebook!", "Login unsuccessful", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}
}
With API v2.4, you can not post into regular groups any more as a normal user.
user_groups permission has been removed (and will be removed for all apps, whatever API version they are using, on Oct. 6, 2015), and only user_managed_groups is available now – and that only gives access (read/write) to the groups the user is an admin of.
https://developers.facebook.com/docs/graph-api/reference/v2.4/group/feed#publish
https://developers.facebook.com/docs/apps/changelog#v2_4_deprecations
Related
I am using Twitterizer dll to post a twit on twitter via oauth method but it give me error.
"Whoa there!
There is no request token for this page. That's the special key we need from applications asking to use your Twitter account. Please go back to the site or application that sent you here and try again; it was probably just a mistake."
And my code is:
using System;
using Twitterizer;
public partial class Home : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var oauth_consumer_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
var oauth_consumer_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
if (Request["oauth_token"] == null)
{
OAuthTokenResponse reqToken = OAuthUtility.GetRequestToken(oauth_consumer_key, oauth_consumer_secret,
Request.Url.AbsoluteUri);
Response.Redirect(string.Format("http://Twitter.com/oauth/authorize?oauth_token+{0}", reqToken.Token));
}
else
{
string requestToken = Request["oauth_token"].ToString();
string pin = Request["oauth_verifier"].ToString();
var tokens = OAuthUtility.GetAccessToken(oauth_consumer_key, oauth_consumer_secret, requestToken, pin);
OAuthTokens accessToken = new OAuthTokens()
{
AccessToken = tokens.Token,
AccessTokenSecret = tokens.TokenSecret,
ConsumerKey = oauth_consumer_key,
ConsumerSecret = oauth_consumer_secret
};
TwitterResponse<TwitterStatus> response = TwitterStatus.Update(accessToken, "Hello everyone, today it's too hot (weather)!!!");
if (response.Result == RequestResult.Success)
{
Response.Write("It's done");
}
else
{
Response.Write("Fail");
}
}
}
}
Please help me..
Seeing no one is giving an answer to your problem, I can suggest the library I am working on.
With Tweetinvi you will be able to do what you want with the following code :
// Step 1 : Redirect user to go on Twitter.com to authenticate
public ActionResult TwitterAuth()
{
var appCreds = new ConsumerCredentials("CONSUMER_KEY", "CONSUMER_SECRET");
// Specify the url you want the user to be redirected to
var redirectURL = "http://" + Request.Url.Authority + "/Home/ValidateTwitterAuth";
var authenticationContext = AuthFlow.InitAuthentication(appCreds, redirectURL);
return new RedirectResult(authenticationContext.AuthorizationURL);
}
// Step 2 : On redirected url
public ActionResult ValidateTwitterAuth()
{
// Get some information back from the URL
var verifierCode = Request.Params.Get("oauth_verifier");
var authorizationId = Request.Params.Get("authorization_id");
// Create the user credentials
var userCreds = AuthFlow.CreateCredentialsFromVerifierCode(verifierCode, authorizationId);
// Do whatever you want with the user now!
ViewBag.User = User.GetAuthenticatedUser(userCreds);
return View();
}
Authentication Documentation : https://github.com/linvi/tweetinvi/wiki/Authentication
I know this is not helping for your Twitterizer but you might want to consider it.
I have this below code to get calendar entries using the google Calendar API (https://developers.google.com/google-apps/calendar/) which uses OAuth2.
It works well.
private IList<string> scopes = new List<string>();
private CalendarService calendarService;
private void InitializeCalendarService()
{
// Add the calendar specific scope to the scopes list
scopes.Add(CalendarService.Scopes.Calendar.GetStringValue());
// Display the header and initialize the sample
CommandLine.EnableExceptionHandling();
CommandLine.DisplayGoogleSampleHeader("Google.Api.Calendar.v3 Sample");
// Create the authenticator
//FullClientCredentials credentials = PromptingClientCredentials.EnsureFullClientCredentials();
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
FullClientCredentials credentials = new FullClientCredentials();
credentials.ClientId = "XYZ.apps.googleusercontent.com";
credentials.ClientSecret = "XYZ";
credentials.ApiKey = "XYZ";
provider.ClientIdentifier = credentials.ClientId;
provider.ClientSecret = credentials.ClientSecret;
OAuth2Authenticator<NativeApplicationClient> auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
// Create the calendar service using an initializer instance
BaseClientService.Initializer initializer = new BaseClientService.Initializer();
initializer.Authenticator = auth;
calendarService = new CalendarService(initializer);
CalendarList list = calendarService.CalendarList.List().Execute();
// do something with the list .. the list is all good
}
public IAuthorizationState GetAuthorization(NativeApplicationClient client)
{
// You should use a more secure way of storing the key here as
// .NET applications can be disassembled using a reflection tool.
const string STORAGE = "google.samples.dotnet.calendar";
const string KEY = "s0mekey";
// Check if there is a cached refresh token available.
IAuthorizationState state = AuthorizationMgr.GetCachedRefreshToken(STORAGE, KEY);
if ((state != null))
{
try
{
client.RefreshToken(state);
return state;
// we are done
}
catch (DotNetOpenAuth.Messaging.ProtocolException ex)
{
CommandLine.WriteError("Using an existing refresh token failed: " + ex.Message);
CommandLine.WriteLine();
}
}
// Retrieve the authorization from the user
string[] array = new string[scopes.Count];
scopes.CopyTo(array,0);
state = AuthorizationMgr.RequestNativeAuthorization(client, array);
AuthorizationMgr.SetCachedRefreshToken(STORAGE, KEY, state);
return state;
}
How can I use the similar OAuth2Authenticator to fetch Contacts?
I am able to fetch contacts using the below code, but its not password-less, I need to get it working using Oath2. The example below uses Gdata contacts api v2. I can see that i can pass through OAuth2Authenticator but im not exactly sure how to do it correctly (i cant see any valid examples in C# on the google site) and fetch the access code based on what the user is selecting.
I cant see how to use OAuth2Authenticator with the contacts api v3 (https://developers.google.com/google-apps/contacts/v3/)
RequestSettings rsLoginInfo = new RequestSettings("", email,pwd);
rsLoginInfo.AutoPaging = true;
ContactsRequest cRequest = new ContactsRequest(rsLoginInfo);
// fetch contacts list
Feed<Contact> feedContacts = cRequest.GetContacts();
foreach (Contact gmailAddresses in feedContacts.Entries)
{
// Looping to read email addresses
foreach (EMail emailId in gmailAddresses.Emails)
{
lstContacts.Add(emailId.Address);
}
}
I ended up doing this by fetching the access code by having a browser control read the Document title value when the user selects the google account and grants access.
eg:
To Generate URL
RedirectURI = "urn:ietf:wg:oauth:2.0:oob"
OAuth2Parameters parameters = new OAuth2Parameters()
{
ClientId = clientId,
ClientSecret = clientSecret,
RedirectUri = redirectUri,
Scope = requiredScope
};
// Request authorization from the user (by opening a browser window):
string url = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
var loginUri = new Uri(url);
// This form has browser control
GoogleLoginForm form = new GoogleLoginForm(loginUri, redirectUri);
var dr = form.ShowDialog();
if (dr == System.Windows.Forms.DialogResult.OK)
{
parameters.AccessCode = form.OAuthVerifierToken;
}
Then In GoogleLoginForm :
We have a browser control and registered browserControl_Navigated event and the do the below. The DocumentTitle contains the AccessCode which is used to generate the token.
private void GoogleLoginForm_Load(object sender, EventArgs e)
{
wbGoogleLogin.Url = _loginUri;
}
private void wbGoogleLogin_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
string fullPath = e.Url.ToString();
WebBrowser control = sender as WebBrowser;
if (control != null && !string.IsNullOrEmpty(control.DocumentTitle) && control.DocumentTitle.Contains("Success code"))
{
_OAuthVerifierToken = control.DocumentTitle.Replace("Success code=","");
DialogResult = DialogResult.OK;
}
}
This way it can be done in the same piece of code, without having to write a complicated callback service of some sort to read the access token back into our system.
Not exactly sure why the calendar api has this built in, and the contacts API doesn't.
Firstly, the quick answer to your question. I believe that the IAuthorizationState has similar properties to OAuth2Parameters. Thus, you should be able to do this (combining it with the code you have for the calender):
OAuth2Authenticator<NativeApplicationClient> auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
//This will call your GetAuthorization method
auth.LoadAccessToken()
RequestSettings settings = new RequestSettings("appName", auth.State.AccessToken);
ContactsRequest cRequest = new ContactsRequest(settings);
// fetch contacts list
Feed<Contact> feedContacts = cRequest.GetContacts();
foreach (Contact gmailAddresses in feedContacts.Entries)
{
// Looping to read email addresses
foreach (EMail emailId in gmailAddresses.Emails)
{
lstContacts.Add(emailId.Address);
}
}
This should work as the RequestSettings allows you to specify an access token. That being said, I myself prefer to use :
var parameters = new OAuth2Parameters()
{
//Client
ClientId = CLIENT_ID,
ClientSecret = CLIENT_SECRET,
RedirectUri = redirectUri,
Scope = "https://www.google.com/m8/feeds",
ResponseType = "code"
};
//User clicks this auth url and will then be sent to your redirect url with a code parameter
var authorizationUrl = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
.
.
.
//using the code parameter
parameters.AccessCode = code;
OAuthUtil.GetAccessToken(parameters);
var settings = new RequestSettings(applicationName, parameters);
var cr = new ContactsRequest(settings);
//Now you can use contacts as you would have before
Although, Ive only tested this with Web Server Apps, so maybe the authenticator is needed for your situation? I found these source codes handy:
OAuth2Demo
IAuthorizationState
OAuth2Authenticator
I having problems with getting the accessToken from the results of my login to facebook.
In the Page_load, my url doesn't get parsed correctly.
GenerateLoginUrl method is working without errors and i can see the accessToken in the QueryString.
I have tried get it from the but that it's not working either.
protected void Page_Load(object sender, EventArgs e)
{
var fb = new FacebookClient();
FacebookOAuthResult result;
if (fb.TryParseOAuthCallbackUrl(Request.Url, out result))
{
if (result.IsSuccess)
{
// result clicked authorized
var accessToken = result.AccessToken;
Label1.Text = accessToken.ToString();
}
else
{
// user clicked cancelled and didn't authorize the app
var error = result.ErrorDescription;
Label1.Text = error;
}
}
else
{
//This is were it always goes
Label1.Text = "not valid facebook url";
}
}
private Uri GenerateLoginUrl(string appId, string extendedPermissions)
{
try
{
dynamic parameters = new ExpandoObject();
parameters.client_id = appId;
parameters.redirect_uri = "local iis ip";
// The requested response: an access token (token), an authorization code (code), or both (code token).
parameters.response_type = "token";
// list of additional display modes can be found at http://developers.facebook.com/docs/reference/dialogs/#display
parameters.display = "popup";
// add the 'scope' parameter only if we have extendedPermissions.
if (!string.IsNullOrWhiteSpace(extendedPermissions))
parameters.scope = extendedPermissions;
// generate the login url
var fb = new FacebookClient();
var url = fb.GetLoginUrl(parameters);
return url;
}
catch (FacebookOAuthException fbex)
{
Label1.Text = fbex.Message;
return null;
}
catch (Exception ex)
{
Label1.Text = ex.Message;
return null;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
string AppId = ConfigurationManager.AppSettings["apiKey"];
string ExtendedPermissions = ConfigurationManager.AppSettings["ExtendedPermissions"];
var url = GenerateLoginUrl(AppId, ExtendedPermissions);
Response.Redirect(url.AbsoluteUri, false);
}
Thanks for your help.
Update:
In the Request.Url the url always is:
http://localhost:23560/Appname/default.aspx
but i can se the real url in the browser and it is:
http://localhost:23560/Appname/#access_token=0000000000&expires_in=3821
So way can't asp.net read the url correctly?
I found the answare and it is:
You have to get the code not token, the code is gonna show in querystring accesstoken gets stripped.
parameters.response_type = "token";
exchange
parameters.response_type = "code";
And then exchange to code to token
dynamic token = fb.Get("oauth/access_token", new
{
client_id = "appid",
client_secret = "appsecret",
redirect_uri = url,
code = Request.QueryString["code"]
});
var accessToken = token.access_token;
this question on google authentication when i try to run below code page successfully load but when i'am click button of login with Google then at debugging display error on this line.
Error at
GetExtension<FetchResponse>()
on line
Var fetchResponse = Response.GetExtension<FetchResponse>()
So what's Problem in this line..i try to search on this problem but i does not get it that solution
protected void Page_Load(object sender, EventArgs e)
{
OpenIdRelyingParty rp = new OpenIdRelyingParty();
var r = rp.GetResponse();
if (r != null)
{
switch (r.Status)
{
case AuthenticationStatus.Authenticated:
NotLoggedIn.Visible = false;
Session["GoogleIdentifier"] = r.ClaimedIdentifier.ToString();
Response.Redirect("Default4.aspx"); //redirect to main page of your website
var fetchResponse = Response.GetExtension<FetchResponse>();
Session["FetchResponse"] = fetchResponse;
var response2 = Session["FetchResponse"] as FetchResponse;
// Use FormsAuthentication to tell ASP.NET that the user is now logged in,
// with the OpenID Claimed Identifier as their username.
string uname = response2.GetAttributeValue(WellKnownAttributes.Name.First) ?? "Guest";
FormsAuthentication.RedirectFromLoginPage(uname, false); //(response.ClaimedIdentifier, false);
break;
case AuthenticationStatus.Canceled:
lblAlertMsg.Text = "Cancelled.";
break;
case AuthenticationStatus.Failed:
lblAlertMsg.Text = "Login Failed.";
break;
}
}
}
protected void OpenLogin_Click(object src, CommandEventArgs e)
{
string discoveryUri = e.CommandArgument.ToString();
OpenIdRelyingParty openid = new OpenIdRelyingParty();
var b = new UriBuilder(Request.Url) { Query = "" };
//var req = openid.CreateRequest(discoveryUri, b.Uri, b.Uri);
//var req = openid.CreateRequest(discoveryUri, b.Uri, b.Uri);
var req = openid.CreateRequest(discoveryUri);
// This is where you would add any OpenID extensions you wanted
// to include in the authentication request. In this case, we are making use of OpenID Attribute Exchange 1.0
// to fetch additional data fields from the OpenID Provider
var fetchRequest = new FetchRequest();
fetchRequest.Attributes.AddRequired(WellKnownAttributes.Contact.Email);
fetchRequest.Attributes.AddRequired(WellKnownAttributes.Name.First);
fetchRequest.Attributes.AddRequired(WellKnownAttributes.Name.Last);
fetchRequest.Attributes.AddRequired(WellKnownAttributes.Contact.HomeAddress.Country);
req.AddExtension(fetchRequest);
req.RedirectToProvider();
}
It should be
var fetchResponse = r.GetExtension<FetchResponse>();
instead of
var fetchResponse = Response.GetExtension<FetchResponse>();
I am trying to implement a functionality to post tweets on twitter in asp.Net and C#. I have got access token, consumer key, callback url etc. I have two buttons "autheticate" and "Send" to authenticate and send tweets respectively.
I am using Twitterizer2 dll for all this. Authenticate and Send buttons' click do not give any error but also do not post anything on twitter. Is there anything I need to add or change? Kindly help.
protected void btnSendTwitterMsg_Click(object sender, EventArgs e)
{
OAuthTokens accessToken = new OAuthTokens();
accessToken.ConsumerKey = "XXXXXXXXXXXXXXXXXXXXXXXX";
accessToken.ConsumerSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXX";
accessToken.AccessToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
accessToken.AccessTokenSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
TwitterStatus.Update(accessToken, "Hello World!!");
}
protected void btnAuthenticate_Click(object sender, EventArgs e)
{
var consumerKey = "XXXXXXXXXXXXXXXXXXXX";
var consumerSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXX";
var callBackUrl = "my call back url";
if (Request.QueryString["oauth_token"] == null)
{
OAuthTokenResponse RequestToken = OAuthUtility.GetRequestToken(consumerKey, consumerSecret, callBackUrl);
Response.Redirect("http://twitter.com/oauth/authorize?oauth_token=" + RequestToken.Token);
}
else
{
OAuthTokenResponse RequestToken = OAuthUtility.GetRequestToken(consumerKey, consumerSecret, callBackUrl);
string oathToken = Request.QueryString["oauth_token"].ToString();
var accessToken = OAuthUtility.GetAccessToken(consumerKey, consumerSecret, RequestToken.Token, RequestToken.VerificationString);
this.lblScreenName.Text = "Hello " + accessToken.ScreenName;
}
}
Thanks
Rakesh
Try Spring.net Twitter, there is an ASP.NET example that does exactly what you want:
http://springframework.net/social-twitter/