AgentFeeble / pgoapi

A Pokèmon Go API written in swift.
17 stars 3 forks source link

PTC login fails most of the time with multiple accounts #4

Closed beeb closed 8 years ago

beeb commented 8 years ago

First of all thanks for this great API, I've been using it for the past couple of days without any problem.

Today I tried using several accounts to speed up scanning since the new API limit is one request per 10 seconds, and I started getting failed login attempts. In fact, most login attempts don't go through. I checked ispokemongodownornot.com and the servers are fine.

I get several kinds of problems. Sometimes the error message says that the ticket "LT-..." is unknown (localized message), sometimes I get a "JSON could not be serialized. Input data was nil or zero length.". Finally, I also get NSCocoaErrorDomain "Invalid value around character 0." on some occasions.

I tried having 1 AlamoFireNetwork per account, and of course 1 api instance per account, but I still get errors.

I also had some security errors at some point because the requested urls were HTTP without SSL but I added an exception in my Info.plist to get around it.

AgentFeeble commented 8 years ago

Thanks, I'm glad its useful to you 😊.

That's quite a strange issue. I've tested with 5 accounts without any issues, using this:

let network = self.network
let authTasks = [
    Auth(network: network).login("username1", password: "password"),
    Auth(network: network).login("username2", password: "password"),
    Auth(network: network).login("username3", password: "password"),
    Auth(network: network).login("username5", password: "password"),
    Auth(network: network).login("username5", password: "password"),
]

Task.whenAllResult(authTasks)
.continueOnSuccessWithTask(.MainThread)
{
    (result: [AuthToken]) -> Task<[(PgoApi, ApiResponse)]> in
    let loginTasks = result.map { PgoApi(network: network, authToken: $0).login() }
    return Task.whenAllResult(loginTasks)
}
.continueWith(.MainThread)
{
    (task: Task<[(PgoApi, ApiResponse)]>) -> () in
    print(task)
    print()
}

I haven't tested it too extensively, but it seems to work just fine for me. How many accounts have you been using, and how often does it fail? Also, using a different PgoApi instance for each account is the way to go, but you shouldn't need different Network for each one.

I've just pushed a few commits for some fixes for some other issues, try with the latest commit. If that doesn't work, could you provide some sample code that reproduces the issue so I can debug it?

beeb commented 8 years ago

Thanks for this, I'll be sure to try. I had issues starting with 2, but up to 6 accounts. I didn't execute all tasks together like you did though, a function was called several times which would login into one account. Let me try with the new commit as well as with Task.whenAllResult. Talk soon

AgentFeeble commented 8 years ago

It should still work executing the logins separately, I can't think of any reason it wouldn't

beeb commented 8 years ago

Hey I'm back, so I tried with your exact code (put the right usernames and passwords of course) and updated to the last commit but I'm still getting the same messages. I'm wondering if this is specific to my accounts or maybe the servers I'm contacting are less compliant than the ones you're testing. Anyway if fails about 95% of the time and the first message is usually "Ticket 'LT-54133079-IBApqON60asIloGm77bnGZVhSZLqDM' is unknown" (but in French and with varying ticket values) then I get a bunch of "JSON could not be serialized. Input data was nil or zero length."

AgentFeeble commented 8 years ago

That is so weird. The errors are happening for me as well, with the same accounts that worked before. I'll look into it now that I can reproduce the issue

AgentFeeble commented 8 years ago

Ok, so it looks like its a cookie issue. It seems like each PgoApi instance needs to manage its own set of cookies. Whats happening now is cookies are being shared between all requests, and I think this is confusing the server into thinking requests belonging to separate accounts (according to the app) all belong to the same session.

I tried disabling cookies, but that just caused each request to fail every time, so we can't do that. One solution is to use a different Network instance for each PgoApi, and configure each with its own cookies storage instead of letting them use the global cookies. I don't like that though, it would be much better to be able to re-use a single Network instance between all requests. I'm just not sure how to manage the cookies on a per PgoApi instance basis though.

Any ideas are welcome

AgentFeeble commented 8 years ago

Upon deeper inspection, it looks like the cookies are only needed for the auth API calls, and can be reset after that. It shouldn't be too difficult to wrangle them up from the response headers, and manually add them to the headers of subsequent auth requests.

Then the cookies can be disabled for all requests. I tested the GetMapObjects API call, confirmed its working without cookies. Hopefully none of the other API requests need cookies. We'll have to see.

It's getting pretty late here now, I'll try get that done tomorrow.

beeb commented 8 years ago

Amazing work there, thanks for your time. I figured it must have been some kind of session problem because of the unrecognized ticket but I don't have enough understanding of the Auth library or protocol to get that done myself. Big up

beeb commented 8 years ago

Looks like the proto buffers have changed also

AgentFeeble commented 8 years ago

Fixed in ce2f2a099e1c10a17dbfbd7421456e1b60ad0168

beeb commented 8 years ago

Cheers! As you might have read from the discussions on AeonLucid/POGOProtos, something in the new protos has not yet been reversed engineered and so the API is not functional. Sitting tight for an update :)