Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON API reauthentication #47

Open
hacker1024 opened this issue Mar 14, 2021 · 2 comments
Open

JSON API reauthentication #47

hacker1024 opened this issue Mar 14, 2021 · 2 comments

Comments

@hacker1024
Copy link
Contributor

The official Android app can reauthenticate without storing the username and password, but I'm unable to do so myself.
It's be great if we could work this out, and add it to the documentation.
Below are my findings after exploring the login system.

Login types

There are four loginType values that can be used with auth.userLogin: user, deviceId, accessToken, and firstIntroToken.

user logs in with a username and password. An example request, with all the common user response parameters removed, looks like this:

{
  "username": "<username>",
  "password": "<password>",
  "appSignature": "0735356f37ee31a95dcbe016fcc8c5b2a6a4ac93",
  "loginType": "user"
}

This login type is used by the Pandora Android app when a user first logs in, but not for subsequent logins.
To reauthenticate expired sessions, and log in from storage, the app uses the deviceId type, which looks like this:

{
  "loginType": "deviceId"
}

As you can see, no loginType-specific user-specific information is required with this login type. Instead, the backend uses the deviceId value sent in every type of login request to authenticate the user.

The deviceId

The deviceId used is generated with UUID.randomUUID() and stored upon first access. The same value is then used for all relevant API requests.

The initial Pandora Android login flow

When the Android app launches for the first time, it does the following:

  1. Authenticate the partner with auth.partnerLogin
  2. Retrieve some UI labels with firstintroduction.v2.startFirstIntroduction
    • This method won't be recognised unless there's a slash before the query string, i.e. .../services/json/?method=....
    • The deviceId is sent in this request, but I don't think this matters due to the next response.
  3. Attempt to log in with the deviceId login type
    • This will always fail with error 1009, which is mapped to a string titled deviceNotFound.
  4. Prompt for the username and password, and then authenticate with the user login type

Reauthentication

When an authentication token expires, subsequent API requests will fail with error 1001 (invalidAuthToken). When this happens, the official Android app will reauthenticate with the deviceId login type.

Additionally, the deviceId login type is used on startup when the user is signed in. The username and password aren't stored.

The issue

When I try to reauthenticate with the deviceId login type, it always fails with an error 1009 - even after I log in with user and provide the same deviceId.

It looks like the Android app is somehow registering the device with Pandora, so reauthentication can be done. This must be happening somewhere in between step 3 of the login flow and reauthentication, but I can't work out how it works.

@hacker1024
Copy link
Contributor Author

I worked it out - the device is associated with the user like so:

Method
user.associateDevice

Request (encrypted)

{
  "deviceId": "<deviceId>"
}

Response

{
  "stat": "ok"
}

@hacker1024
Copy link
Contributor Author

Leaving this issue open as this can be added to the documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant