DirectMessage 403

Jul 14, 2011 at 10:01 PM
Edited Jul 14, 2011 at 10:10 PM

I'm getting a 403 when I try to run the DirectMessage demos in the sample app. To repro, simply uncomment line 123 of Program.cs (DirectMessageDemos.Run(twitterCtx);) and run as normal. The error is thrown from line 1360 of TwitterContext.cs. Is this a known issue? Am I missing something very obvious?

EDIT: I should probably mention that I can successfully get past the step where I enter the PIN given to me by the authorization page.

Coordinator
Jul 14, 2011 at 10:33 PM

Hi,

Any subject of DM's makes me think of a recent event where Twitter changed permissions.  I wrote a post on Configuring OAuth and wrote some documentation to help figure out how to make these settings. The docs are also titled Configuring OAuth, but you should look for the part that explains DM permission settings.  I wonder if that could be the problem?

@JoeMayo

Jul 14, 2011 at 10:49 PM

I took a look at my app's settings page and it does seem that access to DMs was not enabled. I'm still waiting for the change to propagate, but that looks like it should do the trick. Thanks for the help!

Jul 15, 2011 at 3:57 PM

Hmmm, it seems as though that didn't help. I'm also getting a 403 when calling TwitterContext.UpdateStatus("TESTING") after a successful login. My XAuthAuthorizer indicates that it is authorized and my app has permissions to Read, Write and Access direct messages. Any idea what I should be looking for?

Coordinator
Jul 15, 2011 at 4:11 PM

You mentioned that you're using XAuthorizer. Twitter restricts usage of this authentication method: check out their xAuth page.

If the XAuth permissions aren't the issue, I'll need more info on the error.  Stack trace might help.  If you have a TwitterQueryException in the exception chain, it has a Response property that should hold more info from Twitter.  Also, maybe you pull up Fiddler and look at he Twitter API result.

@JoeMayo

Jul 15, 2011 at 4:23 PM

Here's the exception I get when trying to post a tweet. We have been given permission by Twitter to use xAuth, and the XAuthAuthorizer tells me that I'm authenticated (using the Authorize method). In the meantime, I'll use Fiddler to see what's going over the wire.

LinqToTwitter.TwitterQueryException was unhandled
  Message=Error while querying Twitter.
  Source=LinqToTwitter
  HttpError=403 Forbidden
  StackTrace:
       at LinqToTwitter.TwitterExecute.ExecuteTwitter[T](String url, IDictionary`2 postData, IRequestProcessor`1 reqProc)
       at LinqToTwitter.TwitterContext.UpdateStatus(String status, Decimal latitude, Decimal longitude, String placeID, Boolean displayCoordinates, String inReplyToStatusID, Action`1 callback)
       at LinqToTwitter.TwitterContext.UpdateStatus(String status)
       at sandbox.TwitterService.Services.LinqTwitterService.PublishTweet(String message) in C:\Users\Bryan Oltman\Documents\Projects\sandbox.TwitterService\Services\LinqTwitterService.cs:line 186
       at sandbox.ConsoleSandbox.Program.OnLoginComplete(Object sender, EventArgs e) in C:\Users\Bryan Oltman\Documents\Projects\sandbox.ConsoleSandbox\Program.cs:line 37
       at System.EventHandler`1.Invoke(Object sender, TEventArgs e)
       at sandbox.TwitterService.Services.LinqTwitterService.b__3(Object s, RunWorkerCompletedEventArgs e) in C:\Users\Bryan Oltman\Documents\Projects\sandbox.TwitterService\Services\LinqTwitterService.cs:line 75
       at System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
       at System.ComponentModel.BackgroundWorker.AsyncOperationCompleted(Object arg)
       at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
       at System.Threading.ThreadPoolWorkQueue.Dispatch()
       at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
  InnerException: System.Net.WebException
       Message=The remote server returned an error: (403) Forbidden.
       Source=LinqToTwitter
       StackTrace:
            at LinqToTwitter.Utilities.AsyncGetResponse(HttpWebRequest req)
            at LinqToTwitter.TwitterExecute.ExecuteTwitter[T](String url, IDictionary`2 postData, IRequestProcessor`1 reqProc)
       InnerException: 

Coordinator
Jul 15, 2011 at 4:44 PM

Here's something I just noticed, the new permissions restrict access to DMs from xAuth: https://dev.twitter.com/docs/application-permission-model.

@JoeMayo

Jul 15, 2011 at 5:03 PM

Well that's...nice. I'm not too familiar with OAuth, but is there some way I could use my xAuth credentials to get at DMs without redirecting the user to the browser?

Coordinator
Jul 15, 2011 at 5:57 PM

The other authorizers should work fine if you're only using one account.  Just load all four credential properties and you won't need to explicitly authorize - just do the query.  The most recent authorizer added was SingleUserAuthorizer, which allows you to get your credentials from the Twitter page and add them to your application - no OAuth dance required.  There's an example in the LinqToTwitterDemo project.  If you use the other authorizers, you'll need to do the OAuth dance and retain the OAuthToken and AccessToken one time, and then reuse those credentials each time thereafter. 

Here's a quick rundown on what authorizers are available (they differ by technology and purpose):

  • PinAuthorizer: Devices that can't do the full Web OAuth dance.
  • XAuthAuthorizer: Username & Password.
  • WebAuthorizer: ASP.NET Web Forms.
  • MVCAuthorizer: ASP.NET MVC.
  • SilverlightAuthorizer: Silverlight Apps.
  • SingleUserAuthorizer: Pre-keyed tokens for apps that only use one account.

All of this assumes you're operating on behalf of your own account, meaning that your own credentials will work fine.  If you're performing actions on behalf of someone else, then you'll have to do the OAuth dance at least one time for each user.

@JoeMayo