So i've been using Linq-To-Twitter to add Twitter Integration to my Windows 8 Store App, Moreso for playing around with it, but i've come accross a problem. My current authentication codeblock is
var auth = new WinRtAuthorizer
{
Credentials = new LocalDataCredentials
{
ConsumerKey = "",
ConsumerSecret = ""
},
UseCompression = true,
Callback = new Uri("http://linqtotwitter.codeplex.com/")
};
if (auth == null || !auth.IsAuthorized)
{
await auth.AuthorizeAsync();
}
Which works great, unless I go into the authentication screen and click the back button on the top left, to exit authentication without supplying details. at which point i get a TwitterQueryException: Bad Authentication data at:
var timelineResponse =
(from tweet in twitterCtx.Status
where tweet.Type == StatusType.Home
select tweet)
.ToList();
Obviously because the Authentication Information was wrong, I'm trying to find a way to stop proceeding to the rest of the code if the authentication fails/is backed out.
I've tried simple boolean checks to no effect. I've been melting my brain over this for hours, so any help would be greatly appreciated. Thanks a bunch!
You can query Account.VerifyCredentials to ensure the user is logged in before performing any other operation. Here's an example:
const int BadAuthenticationData = 215;
var twitterCtx = new TwitterContext(auth);
try
{
var account =
(from acct in twitterCtx.Account
where acct.Type == AccountType.VerifyCredentials
select acct)
.SingleOrDefault();
await new MessageDialog(
"Screen Name: " + account.User.Identifier.ScreenName,
"Verification Passed")
.ShowAsync();
}
catch (TwitterQueryException tqEx)
{
if (tqEx.ErrorCode == BadAuthenticationData)
{
new MessageDialog(
"User not authenticated",
"Error During Verification.")
.ShowAsync();
return;
}
throw;
}
Your error handling strategy will differ from this, which is just a sample, but it shows you how to know that the error occurred and gives you the opportunity to react to the problem before resuming normal operation.
TwitterQueryException will include the Twitter error code in the ErrorCode property. It also sets Message to the error message that Twitter returns. InnerException provides the underlying exception with the original stack trace, which is often a WebException thrown because of the HTTP error code returned from Twitter.
Related
I am moments from giving up entirely on this workflow.
I set up an Azure account with a REST API, a few other things, and then a b2c AD. After hours and hours of hating my life, I finally have it (somewhat) working to use this AD to sign in, and to be required to access the REST API.
The problem I am now having is that I have tried every single variation of anything I can find only about how to get the profile information of that person who is logged in, and I am getting absolutely nothing.
Even the example files after login don't properly work - it is meant to redirect you to a page that says welcome (username) but the username does not return in my result to
result = await App.AuthenticationClient
.AcquireTokenInteractive(B2CConstants.Scopes)
.WithPrompt(Microsoft.Identity.Client.Prompt.SelectAccount)
.WithParentActivityOrWindow(App.UIParent)
.ExecuteAsync();
None of this is the least bit intuitive. I have read docs but somehow every time I google it I end up on a different page of Microsoft docs with different information.
I do not know what I need to pass to scopes... I do not know how to property get an auth token, as every time I try and use graphs I get an error about an empty or invalid auth token (even after logging in).
Even though I logged in with google successfully, the result above gives me a NULL access token, null tenant id, null scopes, null username under account... the ONLY thing that is correct is the unique ID lines up with the ID I see on the AD users page.
EDIT: the AccessToken is not null actually, I get info there... but every call I try to make that I think should use it is failing.
Ie, if I try to call this to get my info after signing in:
InteractiveAuthenticationProvider authProvider = new InteractiveAuthenticationProvider(App.AuthenticationClient, B2CConstants.Scopes);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
var users = await graphClient.Me.Request().GetAsync();
Note the App.AuthenticationClient is what I used to login above - I have also tried this with
//.Create(B2CConstants.ClientId)
//.Build();
I get this (only partial error so I don't pass out IDs)
Microsoft.Graph.ServiceException: 'Code: InvalidAuthenticationToken
Message: Access token validation failure.
Inner error:
AdditionalData:
date: 2020-10-26T21:45:25
I suggest that you mostly refer Microsoft Docs for any information.
Consider below code to get users details from B2C (This is Android Xamarin Forms page .cs code):
async void OnSignInSignOut(object sender, EventArgs e)
{
AuthenticationResult authResult = null;
IEnumerable<IAccount> accounts = await App.PCA.GetAccountsAsync();
try
{
if (btnSignInSignOut.Text == "Sign in")
{
try
{
IAccount firstAccount = accounts.FirstOrDefault();
authResult = await App.PCA.AcquireTokenSilent(App.Scopes, firstAccount)
.ExecuteAsync();
}
catch (MsalUiRequiredException ex)
{
try
{
authResult = await App.PCA.AcquireTokenInteractive(App.Scopes)
.WithParentActivityOrWindow(App.ParentWindow)
.ExecuteAsync();
}
catch(Exception ex2)
{
await DisplayAlert("Acquire token interactive failed. See exception message for details: ", ex2.Message, "Dismiss");
}
}
if (authResult != null)
{
var content = await GetHttpContentWithTokenAsync(authResult.AccessToken);
UpdateUserContent(content);
Device.BeginInvokeOnMainThread(() => { btnSignInSignOut.Text = "Sign out"; });
}
}
else
{
while (accounts.Any())
{
await App.PCA.RemoveAsync(accounts.FirstOrDefault());
accounts = await App.PCA.GetAccountsAsync();
}
slUser.IsVisible = false;
Device.BeginInvokeOnMainThread(() => { btnSignInSignOut.Text = "Sign in"; });
}
}
catch (Exception ex)
{
await DisplayAlert("Authentication failed. See exception message for details: ", ex.Message, "Dismiss");
}
}
For complete and step by step samples on B2C integration, you can visit below links:
Integrate Microsoft identity and the Microsoft Graph into a Xamarin forms app using MSAL
Integrate Azure AD B2C into a Xamarin forms app using MSAL
Every Example I can find is either very outdated or always comes back 401.
Can anyone at all provide a working example of posting a status update to twitter?
Even the below always fails.
I get redirected to twitter - great. I can confrim the access codes are correct and match my application, but on acutally posting the update - error is unknown...
What on earth is wrong here? Does matter what app I use or which twitter account.
Using Twitteriser2.dll
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,
"Testing!! It works (hopefully).");
if (response.Result == RequestResult.Success)
{
Response.Write("we did it!");
}
else
{
Response.Write("it's all bad.");
}
}
The TwitterRepsonse object has an "ErrorMessage" property. You should probably start by looking at the information in there to give you some guidance.
Why don't you use Tweetinvi. Tweetinvi will allow you to post in 1 line and get error messages in line too. Here is an example.
TwitterCredentials.SetCredentials("Access_Token", "Access_Token_Secret", "Consumer_Key", "Consumer_Secret");
var tweet = Tweet.PublishTweet("Hello!");
if (tweet == null)
{
var exceptionDetails = ExceptionHandler.GetLastException().TwitterExceptionInfos.First().Message;
}
You can find the documentation here : https://tweetinvi.codeplex.com/documentation
Also have a look at https://tweetinvi.codeplex.com/discussions/536895 if you are using it with ASP.NET.
Got it working eventually.
The fault isn't exactly known as I didn't have to change the code but what I did was re-download Twitterizwer and Built it (Required adding a ref to C++ components for what ever reason) and it then worked so I can only see that it was somehow faulty the first time round.
I'm running into a bit of an issue with the Google Calendar API. I'm trying to create an even on a calendar, but I'm getting stuck at querying the calendar service. I'm using this guide I found on codeproject (Guide), and it links you to this authentication guide (Authentication Guide). I was able to make it through step 5 under "OAuth 2.0 flows" on the Authentication guide, and got the access token, and refresh token, but when I attempt to query the calendar service, I get this error:
"Execution of request failed: https://www.google.com/calendar/feeds/default/allcalendars/full", "The remote server returned an error: (401) Unauthorized."
I'm not sure what I'm doing wrong, I authorized the user and have the access token. So I would think I'm missing something small, but I have been banging my head for the past day trying to figure it out.
This is the code I'm using:
Google.GData.Client.GAuthSubRequestFactory authFactory = new Google.GData.Client.GAuthSubRequestFactory("cl", "API Project");
authFactory.Token = "ya29...";
authFactory.KeepAlive = true;
Google.GData.Calendar.CalendarService service = new CalendarService("API Project");
service.RequestFactory = authFactory;
Uri postUri = new Uri(AllCalendarFeed);
Google.GData.Calendar.CalendarQuery CalendarQuery = new Google.GData.Calendar.CalendarQuery();
CalendarQuery.Uri = postUri;
//Errors out on this line:
Google.GData.Calendar.CalendarFeed calFeed = service.Query(CalendarQuery);
string CalendarID = "";
if (calFeed != null && calFeed.Entries.Count > 0)
{
foreach (CalendarEntry CalEntry in calFeed.Entries)
{
//Commented to post the new appointments
//on the main calendar instead of cleverfox calendar
//if (CalEntry.Title.Text.Contains("Cleverfox") == true)
//{
//CalendarID = CalEntry.Title.Text;
CalendarID = CalEntry.EditUri.ToString().Substring(CalEntry.EditUri.ToString().LastIndexOf("/") + 1);
break;
//}
}
}
Any help is greatly appreciated. Thank you.
So I've looked at all the of the suggestions from the Linq to Twitter documentation regarding 401 statuses with Oauth and I honestly don't know what I'm doing wrong.
var auth = new PinAuthorizer
{
Credentials = new InMemoryCredentials
{
ConsumerKey = ConfigurationManager.AppSettings["twitterConsumerKey"],
ConsumerSecret = ConfigurationManager.AppSettings["twitterConsumerSecret"],
//OAuthToken = ConfigurationManager.AppSettings["twitterOAuthToken"], //don't include this
//AccessToken = ConfigurationManager.AppSettings["twitterAccessToken"] //or this for new users.
},
//
UseCompression = true,
GoToTwitterAuthorization = pageLink => Process.Start(pageLink),
GetPin = () =>
{
Console.WriteLine("/nAfter twitter authorizes your application you will be returned here or something/n");
Console.Write("Enter Pin here:");
return Console.ReadLine();
}
};
auth.Authorize();
using (var twitterCtx = new TwitterContext(auth, "https://api.twitter.com/1/",
"https://search.twitter.com/"))
{
try
{
twitterCtx.Log = Console.Out;
Console.WriteLine("Please provide tweet text");
string tweet = Console.ReadLine();
twitterCtx.UpdateStatus(tweet);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
I've ran this using the Pin Authentication method as well as the single user method (providing the oauth keys with config file). I'm able to query tweets but I can't update my status or send direct messages (I receive a 403 forbidden when I try to DM). I've provided a callback URL (albeit fake) so I can't think of why this isn't working. Any help would be appreciated.
PS this runs in Main, not sure if that matters
All you need is this overload of the TwitterContext ctor and it will use the proper base URLs:
new TwitterContext(auth)
The example you're using is for v1.0 URLs and LINQ to Twitter is on Twitter API v1.1 now. It will default to the proper base URLs.
If you're querying okay, but getting errors on update and DM, double check to make sure you aren't trying to tweet the same text. That's why I append a DateTime.Now to the end of test tweets - to guarantee uniqueness.
I'm a noob in LinQ and having troubles with Linq2Twitter and Twitter API in general.
I cannot understand how to get an authorized user's screen name, id, and name after a successful authorization.
I searched discussion threads online and the only advice I got from Joe was to use async call when querying for results. Except that I don't have the MaterializedAsyncCallback for some reason so I'm using AsyncCallback instead.
Here are the steps that I take all the way from authorizing to attempting to obtain the user's info:
Create a PinAuthorizer with my consumer key and secret as credentials
this.pinAuth = new PinAuthorizer
{
Credentials = new InMemoryCredentials
{
ConsumerKey = CONSUMER_KEY,
ConsumerSecret = CONSUMER_SECRET
},
UseCompression = true,
GoToTwitterAuthorization = pageLink =>
Dispatcher.BeginInvoke(() => {
WebBrowser.Navigate(new Uri(pageLink + "&force_login=true", UriKind.Absolute));
})
};
Authorize Begin
this.pinAuth.BeginAuthorize(resp => ...
Enter the pin and thus getting access token and secret in pinAuth.OAuthTwitter:
pinAuth.CompleteAuthorize(
this.pin,
completeResp => Dispatcher.BeginInvoke(() =>
{ ...
Then, I try to get the user ... with an async call as that's what Joe Mayo recommended in other threads.
ITwitterAuthorizer auth = pinAuth;
TwitterContext twitterCtx = new TwitterContext(pinAuth);
(from user in twitterCtx.User
where user.UserID != "JoeMayo"
select user).AsyncCallback(asyncResponse => {
var response = asyncResponse.ToList();
User acc = response.FirstOrDefault();
// Anything in this block is pointless
// as I never get into this async callback block.
// But this is where I expect to get the user's info
// (screen name, name, id, etc.)
});
I never get the async response.
(I also do not have MaterializedAsyncCallback for some reason).
How do I get the authorized user's screen name, id, and name?
You didn't actually fire the query at all!
(from user in twitterCtx.User
where user.UserID != "JoeMayo"
select user).AsyncCallback(users => {
// result is in users variable
var user = users.SingleOrDefault();
if(user != null)
{
// use user here.
}
}).SingleOrDefault();