maierfelix / POGOserver

Pokemon GO server emulator
GNU General Public License v3.0
460 stars 198 forks source link

[FEAT REQ] Change logic behind player authentication/identification #277

Open Zaephor opened 7 years ago

Zaephor commented 7 years ago

Posting this since I haven't had the free time to catch up on ES6 and fully work through the application workflow. (And because I saw commits 33cca65938cb0f7ae5648ab6f9157e7c8d860288 and 4fdaf71998481ea574ef97eafc7d9752021c3a34 copying in my CLAIM_CODENAME test files)

Current serverside logic depends on the IP for user identification. This runs into issues when there are multiple players sharing a single internet connection(Home wifi/Hot spot/etc), or the server is put behind a reverse proxy or load balancer for scaling. This also means that a user logging in/out between multiple accounts in the client-side app doesn't actually change anything.

This seems to be enforced by the server checking who the client is(IP) before actually performing any protobuf breakdown. (Or I'm really lost trying to go through the ES6 workflow) (https://github.com/maierfelix/POGOserver/blob/master/src/models/World/players.js#L25)

As far as my research and testing, the auth_ticket object is actually just echo'd back at the server by the client, with almost no validation or checking client-side. At most, when the expire_timestamp_ms variable expires, the client will attempt a reauth.

From my own experiments, I treat the 3 auth_ticket variables as:

start: new Buffer(player.email),
expire_timestamp_ms: ((new Date).getTime() + (1000 * 60 * 30)),
end: new Buffer(<session key>),

With session key either being the index/hash value from a sessions table(Requires DB table), or a server-signed JWT to confirm that the entire auth_ticket object is valid(Doesn't require a DB table). This should allow the server to properly use the auth_ticket object like a standard session token.

vankxr commented 7 years ago

Did you test this?

I tried to send an auth ticket once and as I remember the APP was sending a wrong one back.

Zaephor commented 7 years ago

An early test I was doing in trying to build a server from scratch showed this working correctly, though that also included trying to mix protobufjs with POGOProtos to always run with the latest Protos. So I had a mess of various debugging.

The process I had functioning was:

From my testing, any time you transmit an auth_ticket object to the client, it will replace locally it until the token is expired. If you leave it null, it continues to use the last known auth_token.

Additionally I had started using pogobuf for quick/auto client testing.

When it came back to the server as 2 buffers and a timestamp, all I had to do was perform requestObj.auth_ticket.start.toBuffer().toString() to convert it from BytebufferJS->Buffer->String for use.

I ended up dropping my own scratch server project due early feature creep before really being able to do anything with it at all(DNS server, 2 parallel proxies...).

OhnO395 commented 7 years ago

image

T_T

vankxr commented 7 years ago

That's nice. I am also developping My own server from scratch and will try this for sure

maierfelix commented 7 years ago

@Zaephor @Vankxr Be careful with protobufjs, it serializes various packets wrong. As far as I remember right with Encounter, FortSearch, GetPlayerProfile and sfidaActionLog. I used it in early versions, but got unavoidable super-weird packet results. I saw (rastapasta)[https://github.com/rastapasta] uses the native binding for his mitm tool - by doing so as well solved all problems.

vankxr commented 7 years ago

Serializes wrong? I use the 3 you specified, just a matter of working around the packed bug on protobufjs. Check @cyraxx/node-pogo-protos for the function to work around it

Zaephor commented 7 years ago

Did you test this?

@Vankxr incase you were curious, I setup a repo with the last working copy of my "scratch" written emulator. Also switched it over to the more common protobuf libraries rather than the one I was trying to build. https://github.com/Zaephor/pogo-emulator

It's basically Expressjs for urls+middleware and Loopback for DB/ORM. But it does demonstrate the auth_ticket being returned to the server correctly to identify the user. With this version I'm able to login->logout no problem between multiple accounts on the same device, as well as use a range of devices on a single IP without hitting the user-account collusion I described earlier. It also updates the auth_ticket on it's own when it detects some device information, incase we need the platform name later.