JorgenPhi / php-snapchat

A PHP library for the Snapchat API - With Commit History
MIT License
259 stars 73 forks source link

New Version #89

Open gidbot-old opened 9 years ago

gidbot-old commented 9 years ago

In snapchat_agent the version needs to be changed to '9.0.1'

Additionally, has anyone been able to post stories since the update?

Snowlav commented 9 years ago

I'm on the 9.0.2.1 beta and a lot has changed, though posting stories shouldn't give any issues. how are you uploading stories?

gidbot-old commented 9 years ago

$snapchat = new Snapchat('uname', 'password'); $id = $snapchat->upload( Snapchat::MEDIA_IMAGE, file_get_contents('/path/to/image.png') ); $snapchat->send($id, array('uname'));

liamcottle commented 9 years ago

If you are using the 9.0+ user agent, you need to make sure you have implemented the new Login parameters.

Check out my working 9.0.2.0 login request here:

http://github.com/liamcottle/snaplib On 30/01/2015 1:07 pm, "gbrosenthal" notifications@github.com wrote:

In snapchat_agent the version needs to be changed to '9.0.1'

Additionally, has anyone been able to post stories since the update?

— Reply to this email directly or view it on GitHub https://github.com/JorgenPhi/php-snapchat/issues/89.

gidbot-old commented 9 years ago

Logging in isnt the issue. Im able to get users etc... so i know im authenticated

liamjack commented 9 years ago

Make sure you send all the following data correctly. This hasn't changed at all compared to 8.1.1

User-Agent: Snapchat/9.0.2.0 (Nexus 4; Android 17; gzip)

/bq/retry_post_story

Description

Used to post a story

Request

Response

gidbot-old commented 9 years ago

Sorry, just realized that my example was sending to single users. But i havent been able to do that either haha.

gidbot-old commented 9 years ago

But it also looks like a lot of those variables are not set by this library. Ie not in 'function setStory' in the snapchat class, nor 'function post' in the snapchat_agent one

liamjack commented 9 years ago

The library is not exactly up to date, if you want it to work you need to know what the actual application sends to the API, and then you have to add / remove parameters to each request in the library.

Here is some API documentation : https://github.com/JorgenPhi/php-snapchat/wiki/API-v2-Research

Snowlav commented 9 years ago

I'm getting real tired of snapchat and their api updates, I'll tell you that much

liamjack commented 9 years ago

Well the API updates are a good thing, it brings new features to the application for us to use and abuse. We just need to keep up with constantly analyzing the application's API calls.

Snowlav commented 9 years ago

The latter is hard though, I do not mind it actually, but snapchat is not only adding user features but I have the feeling they are also making it harder for us to abuse every update.

Scape373 commented 9 years ago

Any fix for this yet? I can login and update snaps and save snaps, but cannot upload or set a story. It just uploads a blank gray thumbnail and disappears when i try to click on it This literally worked yesterday with no change. I tried updating my user agent to 9.0.2, and 9.0.1 and still doesn't work.. What am i missing?

$final1 = "http://-snip-watermark.php?filename=$value"; $id = $snapchat->upload( Snapchat::MEDIA_IMAGE, file_get_contents($final1)); $snapchat->setStory($id,5);

const VERSION = 'Snapchat/9.0.1.0'; CURLOPT_USERAGENT => 'Snapchat/9.0.1.0 (Nexus 4; Android 17; gzip)',

gidbot-old commented 9 years ago

I've been able to upload (get a 200 Response), but I havent been able to send single snaps or set my story. If anyone has been able to get this library working in the last couple days, please share.

Snowlav commented 9 years ago

Are you uploading a JPG image ? What responses do you get?

Can you elaborate "I can login and update snaps and save snaps, but cannot upload or set a story. It just uploads a blank gray thumbnail and disappears when i try to click on it" Do you mean on the application?

Snowlav commented 9 years ago

Remember this lib is outdated guys, if you are mixing new headers with old endpoints, or old endpoints with new endpoints etc, it will not work. Which endpoint are you guys using to login and which are you using to set story.

In the new versions of snapchat you no longer need to use upload and send but simply post to story.

We need more information than that is given right now.

JorgenPhi commented 9 years ago

Speaking of outdated, if anyone wants access to accept pull changes and write to the repo directly, let me know. I don't have the time to keep this relevant. On Jan 30, 2015 2:14 PM, "Snowlav" notifications@github.com wrote:

Remember this lib is outdated guys, if you are mixing new headers with old endpoints, or old endpoints with new endpoints etc, it will not work. Which endpoint are you guys using to login and which are you using to set story.

In the new versions of snapchat you no longer need to use upload and send but simply post to story.

We need more information than that is given right now.

— Reply to this email directly or view it on GitHub https://github.com/JorgenPhi/php-snapchat/issues/89#issuecomment-72263354 .

Scape373 commented 9 years ago

So what you are saying is my code should look more like this now?:

It's still not working.. :(

Gets contents of folder uploads the images in the folder

$directory = 'saved'; $scanned = array_diff(scandir($directory), array('..', '.')); foreach($scanned as $value){ //Watermark $snapchat->setStory($value,5); var_dump($value); }

$value comes out as a string: string '6.jpg' (length=5)

liamjack commented 9 years ago

Logging in with 9.0.2.0's API is pratically impossible for the Android version. They have started checking device tokens, so you need to fetch a valid device token before logging in, and there is a new "Authorization" header containing a Google OAuth2 token....

Snowlav commented 9 years ago

@cuonic isn't the google oath2 token optional, and by device token do you mean a device ID ? These can be generated pretty easy right ?

liamjack commented 9 years ago

It's no longer option, if you don't provide the "ptoken" on login you get "401 UNAUTHORIZED", if you create one randomly you get "Oh no! Your login temporarily failed, so please try again later. If your login continues to fail, please visit https://support.snapchat.com/a/failed-login :)"

The message doesn't change when adding or removing the Authorization header

On 31/01/2015 18:49, Snowlav wrote:

@cuonic https://github.com/cuonic isn't the google oath2 token optional, and by device token do you mean a device ID ? These can be generated pretty easy right ?

— Reply to this email directly or view it on GitHub https://github.com/JorgenPhi/php-snapchat/issues/89#issuecomment-72327909.

Snowlav commented 9 years ago

hmm so we would need to fetch valid info first using fiddlr or something alike, and once logged in store auth token, that is if we are using the 9.0.2.0 api. Is this correct, or not possible?

liamjack commented 9 years ago

Yeah, but that's not really a solution, you shouldn't have to run the official application along side just to get tokens, we need to emulate this.

On 31/01/2015 18:56, Snowlav wrote:

hmm so we would need to fetch valid info first using fiddlr or something alike, and once logged in store auth token, that is if we are using the 9.0.2.0 api. Is this correct, or not possible?

— Reply to this email directly or view it on GitHub https://github.com/JorgenPhi/php-snapchat/issues/89#issuecomment-72328243.

Snowlav commented 9 years ago

I like this challenge

Snowlav commented 9 years ago

But I question if it's feasible

Snowlav commented 9 years ago

is it possible to bring out an api lib for a previous no longer supported by snapchat version, without getting our accounts banned?

liamjack commented 9 years ago

Well using 8.1.1's API for the moment will probably work for a while, but then they will kill it.

On 31/01/2015 19:05, Snowlav wrote:

is it possible to bring out an api for a previous no longer supported by snapchat version, without getting our accounts banned?

— Reply to this email directly or view it on GitHub https://github.com/JorgenPhi/php-snapchat/issues/89#issuecomment-72328573.

Snowlav commented 9 years ago

Any other options? Long term solutions?

hako commented 9 years ago

I've seen the OAuth thing before it became mandatory in the beta, AFAIK it looks like signing up does not have to use OAuth though. And the ptoken is new to me.

@Snowlav We can only look inside the APK I guess, unless there are other solutions.

Snowlav commented 9 years ago

@hako inside the APK you mean modding the apk or reverse engineering it in the hopes of finding a solution?

liamcottle commented 9 years ago

ptoken is the Google Cloud Messaging Registration ID, it's the same value that you post to /ph/device in the device_token param. It's used by the snapchat server to send notifications to your device via GCM.

As for logging in, I have noticed they have made the header Authorization mandatory. Also, it must be a valid one...

If you pass a blank value in the Authorization header, you'll get a 401, the snapchat server checks the Google servers (I guess) to check if the Bearer value is legit, if not 401...

I have made a successful login by using an already created bearer for the Authorization header from a snapchat app login request.

So, if we can make valid value for the Authorization header, we can get in.

liamjack commented 9 years ago

I'm working on generating the device token signature for login at the moment, it's pretty simple. The Authorization header is an OAuth2 token from Google based on Snapchat's client secret

On 31/01/2015 23:04, Liam Cottle wrote:

|ptoken| is the Google Cloud Messaging Registration ID, it's the same value that you post to |/ph/device| in the |device_token| param. It's used by the snapchat server to send notifications to your device via GCM.

As for logging in, I have noticed they have made the header |Authorization| mandatory. Also, it must be a valid one...

If you pass a blank value in the |Authorization| header, you'll get a 401, the snapchat server checks the Google servers (I guess) to check if the Bearer value is legit, if not 401...

I have made a successful login by using an already created bearer for the |Authorization| header from a snapchat app login request.

So, if we can make valid value for the |Authorization| header, we can get in.

— Reply to this email directly or view it on GitHub https://github.com/JorgenPhi/php-snapchat/issues/89#issuecomment-72339207.

liamcottle commented 9 years ago

Ok,

So did a bit of digging, and because the OAuth token is tied to the users Google Account, what I did was remove my local Google Accounts, and then perform a snapchat login.

I noticed that in the Authorization header that if you don't have a Google Account connected, the official Snapchat app sends Bearer ng as the Authorization header...

Doing this still returns a 401 if you pass in a blank ptoken which is a GCM reg id...

Sending a random ptoken also fails...

So, what snapchat server is doing, is if it gets Bearer ng as the Authorization header it asks Google if the notification ID passed in ptoken is correct...

I was able to make a successful login request by sending: Header: Authorization: Bearer ng Param: ptoken with an actual Google GCM ID.

Snowlav commented 9 years ago

can Google GCM IDs be generated in bulk ?

Thanks for all the research to both you and cuonic btw :)

liamjack commented 9 years ago

Ideally we need to be able to generate both the GCM and Google OAuth token outside of Android, I've got all the POST parameters for these requests, I'll take a look

On 31/01/2015 23:36, Liam Cottle wrote:

Ok,

So did a bit of digging, and because the OAuth token is tied to the users Google Account, what I did was remove my local Google Accounts, and then perform a snapchat login.

I noticed that in the |Authorization| header that if you don't have a Google Account connected, the official Snapchat app sends |Bearer ng| as the |Authorization| header...

Doing this still returns a 401 if you pass in a blank |ptoken| which is a GCM reg id...

Sending a blank or random |ptoken| also fails...

So, what snapchat server is doing, is if it gets |Bearer ng| as the |Authorization| header it asks Google if the notification ID passed in |ptoken| is correct...

I was able to make a successful login request by sending: Header: |Authorization: Bearer ng| Param: |ptoken| with an actual Google GCM ID.

— Reply to this email directly or view it on GitHub https://github.com/JorgenPhi/php-snapchat/issues/89#issuecomment-72340403.

liamcottle commented 9 years ago

A Google GCM ID is specific to the device and application that it is requested for, the device itself has to request it from the Google Server.

I've just factory reset one of my S5 test devices so I can check GCM registration requests without any old data being sent.

Might be able to create some "virtual" device IDs, that work...

See what I can do...

EDIT:

@cuonic that way it will work without needing an Android Device. Such as PHP libraries like this.

ddaddy commented 9 years ago

Just listening from the outskirts. Have you considered how it must be different for iOS? They don't have GCM so completely different id's and from what I know, the apple messaging id's can't be confirmed.

liamcottle commented 9 years ago

I thought about this a little while ago, I'll just setup an iOS device with proxy stuff, and see what I get.

liamcottle commented 9 years ago

Snapchat on iOS sends X-Snapchat-Client-Token which is different on each login request.

Headers: screen shot 2015-02-01 at 12 07 19 pm

Params: screen shot 2015-02-01 at 12 07 48 pm

... because I don't know how to reverse engineer iOS apps, I can't see how the X-Snapchat-Client-Token is generated... Anyone know how to do so? Or is it not possible...

Also note, the same as Android, both apps will send nt=1 in the login request if it hasn't got the device token fro snapchat... (Which is returned in login response when nt=1)

Next time the device logs in, it will send dsig and dtoken1i where dsig is a signature generated from the first login token and other device params... Not sure what dtoken1i is yet, haven't looked into it.

mgp25 commented 9 years ago

@liamcottle its possible but its harder to reverse it, its better to reverse android apk, im uploading tomorrow a patched apk for you guys, it will print everything in logcat and it will help us in next releases :)

Regards

Snowlav commented 9 years ago

Together we can do this :D

liamcottle commented 9 years ago

100%

liamjack commented 9 years ago

@liamcottle

dtoken1i is the Device token ID dtoken1v is the Device token value dsig is the Device token signature

dsig is the SHA256 HMAC of [USERNAME]|[PASSWORD]|[TIMESTAMP]|[REQUEST_TOKEN] using dtoken1v as the secret key.

You can obtain a new Device token set (dtoken1i and dtoken1v) by posting to /loq/device_id without authentication, only a timestamp is required

public function getDeviceToken() 
{
    $timestamp = parent::timestamp();

    $result = parent::post(
        '/loq/device_id',
        array(
            'timestamp' => $timestamp,
        ),
        array(
            parent::STATIC_TOKEN,
            $timestamp,
        ));

    return $result;
}

The signature (dsig) is generated by the following function in the 9.0.2.0 Android application on LoginTask :

public String a(DeviceToken devicetoken, String s, String s1, String s2, String s3)
{
    SecretKeySpec secretkeyspec = new SecretKeySpec(devicetoken.b().getBytes(Charsets.UTF_8), "HmacSHA256");
    String s4;
    Mac mac = Mac.getInstance("HmacSHA256");
    mac.init(secretkeyspec);
    s4 = (new String(Hex.encodeHex(Arrays.copyOf(mac.doFinal((newStringBuilder()).append(s).append("|").append(s1).append("|").append(s2).append("|").append(s3).toString().getBytes(Charsets.UTF_8)), 10)))).toLowerCase(Locale.ENGLISH);
    return s4;
    Object obj;
    obj;
    _L2:
    Timber.a("DeviceTokenUtils", ((Throwable) (obj)));
    return null;
    obj;
    if (true) goto _L2; else goto _L1
    _L1:
}

s is the username s1 is the password s2 is the timestamp s3 is the request token

devicetoken.a() is the Device token ID devicetoken.b() is the Device token value

Also I've noticed that the timestamp format has changed with the newer versions, there are now 13 digits (Example: 1422744159226)

liamcottle commented 9 years ago

I just finished coding this in Java ;)

I believe they are using System.currentTimeMillis(); instead of new Date().getTime();

Edit:

You also get a Device Token ID and Device Token Value by sending nt=1 in the /loq/login request.

liamjack commented 9 years ago

@liamcottle I'm trying to implement the hashing function in PHP but I'm not able to reproduce all the getBytes, and I have no idea how the mac function works on byte arrays.

liamjack commented 9 years ago

@liamcottle Could you send me an example of all the different variables (username, password, timestamp, request token), the dtoken1v and the dsig for a specific timestamp and request token so that I can keep trying the HMAC function until it produces the correct output ?

liamcottle commented 9 years ago

From Login Request (using nt=1)

dtoken1i: 1bd3c0fb-8c5a-4633-acfa-8f96cda1a405
dtoken1v: neu8H3+7TgDwq7GUcmwSpQ==

Next Login Request with DSIG

dsig: bd05d90bef579a1b744d
dtoken1i: 1bd3c0fb-8c5a-4633-acfa-8f96cda1a405
req_token: 93099f5b6a1136b86ea04ee5fcad85d4b9e64d8b190cda8119b48614d0c510db
timestamp: 1422755390239
username: govjnwogl
liamjack commented 9 years ago

Could you provide the password as well, it's used to create the dsig. You can send it via email if you want (cuonic@cuonic.com). Promise I will not use it or change it :)

On 01/02/2015 02:52, Liam Cottle wrote:

From Login Request:

dtoken1i: 1bd3c0fb-8c5a-4633-acfa-8f96cda1a405 dtoken1v: neu8H3+7TgDwq7GUcmwSpQ==

Next Login with DSIG:

dsig: bd05d90bef579a1b744d dtoken1i: 1bd3c0fb-8c5a-4633-acfa-8f96cda1a405 req_token: 93099f5b6a1136b86ea04ee5fcad85d4b9e64d8b190cda8119b48614d0c510db timestamp: 1422755390239 username: govjnwogl

— Reply to this email directly or view it on GitHub https://github.com/JorgenPhi/php-snapchat/issues/89#issuecomment-72347010.

liamcottle commented 9 years ago

Yeah sorry, forgot to copy it:

Username: govjnwogl
Password: snapchat-test-1
liamjack commented 9 years ago

@liamcottle Thank you very much :)

liamcottle commented 9 years ago

This works mint:

<?php

$dtoken1i = "1bd3c0fb-8c5a-4633-acfa-8f96cda1a405";
$dtoken1v = "neu8H3+7TgDwq7GUcmwSpQ==";
$req_token = "93099f5b6a1136b86ea04ee5fcad85d4b9e64d8b190cda8119b48614d0c510db";
$timestamp = "1422755390239";
$username = "govjnwogl";
$password = "snapchat-test-1";

$expected_dsig = "bd05d90bef579a1b744d";

$dsig = hash_hmac('sha256', $username . "|" . $password . "|" . $timestamp . "|" . $req_token, $dtoken1v);
$dsig = substr($dsig, 0, 20);

echo "Expected: " . $expected_dsig;
echo "<br/>";
echo "Result: " . $dsig;

?>