Multiple PinAuthorizers in one application

Nov 4, 2013 at 5:24 AM
Hello,
I am creating an unfollower tracking application for Windows Phone, and I'm trying to include multiple account support using PinAuthorizers. I can authorize one account fine, but when I try to authorize the second one, the PinAuthorizer.GoToTwitterAuthorization action is never called, even though I do call the PinAuthorizer.BeginAuthorize method.
I was wondering if Twitter simply doesn't allow developers to use the same Consumer Key and Consumer Secret in one application for multiple accounts, or if this is an error with the way I'm coding or even LinqToTwitter.
Thanks!
Elliott
Coordinator
Nov 4, 2013 at 5:42 AM
Hi Elliott,

There are a couple ways to handle this: use a new Credential store or reset user credentials when switching to the new user. In the first option, you can assign a new Credentials (e.g. InMemoryCredentials) object to the authorizer with only ConsumerKey/ConsumerSecret. For the second option, set the OAuthToken and AccessToken properties of the Credentials to null. You can find the Credentials property on the authorizer. If you didn't keep a reference to the authorizer, you can get it through the TwitterContext in AuthorizedClient. Assuming twitterCtx is an instance of TwitterContext, you can do something like:

twitterCtx.AuthorizedClient.Credentials

LINQ to Twitter authorizers are designed so that if all 4 credentials are present, it won't force the user to go through the authorization process an you can just use the authorizer. This is intentional so that you don't have to make the user authorize on every query, which would be pretty annoying to them. So, whenever the OAuthToken and AccessToken are empty (null), TwitterContext can go through the authorization process. When it does this, it will fill OAuthToken and AccessToken with the credentials for the user that just authorized. You can check this, but I think you have OAuthToken and AccessToken filled with the first user's credentials and you need to clear those out.
@JoeMayo
Nov 4, 2013 at 6:16 AM
Hello Joe,
Thanks for the quick response!
I apologize, as I did not thoroughly explaining my situation in my first post, so I will now!

So, in my application, I have a static class called AppData containing all the data: a list of each account's data, a list of each account's InMemoryCredentials, and an int called ProfileIndex, which helps the app keep track of what profile it's using.
To fetch the valid authorizers and data for each account, I must simply request AppData.CurrentAuthorizer, which returns a new PinAuthorizer with the credentials of CredentialCollection[ProfileIndex]. This all works fine and dandy with a single account; the problem comes when I try to add another account.

In my main page, I have a private PinAuthorizer called _authorizer, as it is simply used to retrieve the account's credentials, then it passes them onto the AppData.CredentialCollection, where they are stored for use throughout the app. It is defined as:
            _authorizer = new PinAuthorizer()
                 {
                     Credentials = new InMemoryCredentials { ConsumerKey = "XXXXXXX", ConsumerSecret = "XXXXXXX" },
                     UseCompression = true,
                     GoToTwitterAuthorization = pageLink => Dispatcher.BeginInvoke(() => OAuthBrowser.Navigate(new Uri(pageLink, UriKind.Absolute)))
                 };
When I want to authenticate a new user, I open a window containing the OAuthBrowser, and the user fills out the information. Upon completing authorization, _authorizer.Credentials is added to AppData.CredentialCollection, and _authorizer.Credentials is reset:
                            AppData.CredentialCollection.Add(_authorizer.Credentials as InMemoryCredentials);
                            _authorizer.Credentials = new InMemoryCredentials
                            {
                                ConsumerKey = "XXXXXXX",
                                ConsumerSecret = "XXXXXXX",
                                OAuthToken = null,
                                AccessToken = null
                            };
The first user works completely fine, and when I go back to authorize another account and call _authorizer.BeginAuthorize, nothing happens. I've inserted a breakpoint at the OAuthBrowser.Navigate call, and it simply is never called.
All in all, I do clear out the OAuthToken and AccessToken values of _authorizer after they are stored in AppData.CredentialCollection. So that isn't the problem. I just can't figure out what is, then!

Now that you have a little more detail on my situation, do you know what may be causing the problem?
Thanks again!
Elliott
Nov 4, 2013 at 6:19 AM
PS:
I can confirm that when I go around the second time to add another account, _authorizer.IsAuthorized is set to false when I call _authorizer.BeginAuthorize, so I have absolutely no clue what is causing the issue :(
Thanks!
Elliott
Coordinator
Nov 4, 2013 at 8:35 AM
I guess that won't work - I'll have to take a look at it. It might be better to just create a new instance of the PinAuthorizer and assign it to a new instance of TwitterContext when switching users.
Nov 5, 2013 at 1:51 AM
Hey Joe,
Thanks for looking into it!
I just wanted to add that after I add one account to the application and then exit the app, which serializes the account's data and saves it, I still cannot authorize a second account upon relaunching the app. So, I can physically close the app and restart it, resetting the value of _authorizer to its original state which worked for authorizing the first user. Even when _authorizer is completely reset, the authentication of a second user doesn't work. So, I'm certain that the issue is caused by either the Twitter APIs or LINQ to Twitter not allowing multiple OAuthTokens in one application. However, I've seen other apps on platforms like iOS that use OAuth, and therefore the Twitter API, and still have multiple account support, so I'm guessing it may be something to do with the way the PinAuthorizer handles the second request to authenticate a user.
If you find anything else out, please let me know!
Your assistance is greatly appreciated!
Elliott
Coordinator
Nov 10, 2013 at 12:58 AM
I spent some time looking at this and am not reproducing your problem. I have a WindowsPhoneDemo project in the downloadable source code and am able to hit breakpoints, change credentials and get the results I expect. Make sure that you're actually executing the logic that resets the credentials before attempting the query. You might be seeing a race condition.
Nov 10, 2013 at 7:59 PM
Hello Joe,
I think I may have found where the problem is coming from.

I tried inserting a breakpoint in the Action<TwitterAsyncResponse<object>> parameter of BeginAuthorize, and I an error occurs when trying to authorize a second account.
The state of the TwitterAsyncResponse<object> is TwitterApiError, and the message is "Error during LINQ to Twitter processing. Please see Error property for details."
The exception is of type Ionic.Zlib.ZlibException, with a message saying, "Bad GZIP header." The stack trace is:
at Ionic.Zlib.ZlibBaseStream._ReadAndValidateGzipHeader()
at Ionic.Zlib.ZlibBaseStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at Ionic.Zlib.GZipStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at LinqToTwitter.OAuthTwitter.GetHttpResponse(HttpWebResponse res)
at LinqToTwitter.OAuthTwitter.<>c__DisplayClass48.<GetRequestTokenAsync>b__47(IAsyncResult ar)

I'm not quite sure what this means, so I was hoping you could help me out!
Thanks!
Elliott
Coordinator
Nov 10, 2013 at 10:57 PM
Try setting UseCompression to false or don't set it at all.
Nov 10, 2013 at 11:43 PM
Hello Joe,
Not setting UseCompression at all did not work and the error still occurred, However, I did find a way to fix my issue!
I recognized GZip from somewhere, and lo and behold, when creating my TwitterContexts, I did so with
new TwitterContext(CurrentAuthorizer, SharpGIS.WebRequestCreator.GZip)
I think I saw this in an example project somewhere, so I thought it was mandatory, However, I simply removed the second parameter when setting my TwitterContext and the application starting being able to add more accounts... I'm not sure how setting a property of the TwitterContext affects a PinAuthorizer though.
But, the problem is fixed and that's all that matters! Thank you so much for your help along the way!
Elliott