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

Add zeroconf based login #17

Closed
plietar opened this issue Dec 30, 2015 · 7 comments
Closed

Add zeroconf based login #17

plietar opened this issue Dec 30, 2015 · 7 comments

Comments

@plietar
Copy link
Owner

plietar commented Dec 30, 2015

No description provided.

@CoDEmanX
Copy link

Is this just a TODO or do you need to research this first? (e.g. how the bearer token is generated)

@plietar
Copy link
Owner Author

plietar commented Dec 31, 2015

A bit of both.
I'm working on it right now. I am able to receive the token from the controlling device and decrypt it (It uses DH to generate a shared secret, HMAC to derive a key from it and AES to encrypt the token).

I now need to figure out what the protocol is to login using that token, but that shouldn't take too much time. Just a lot of assembly reading to do 😄

@CoDEmanX
Copy link

Okay, good luck on that 👍

Just for the record: one can distinguish between two major types of Spotify clients, "full" clients and "thin" clients.

  • Full clients let you enter either Spotify or Facebook credentials (raw username and password), they usually store them permanently and will login using these credentials. They register as Spotify devices via Mercury/Hermes/Spirc and also retrieve other devices via the Spotify services over the internet. They try to discover thin clients in the local network, but do not advertise themselves as spotify connect speakers (no answer records in the DNS packets).
  • Thin clients have limited ways or none to enter credentials, such as speakers or audio dongles. They advertise themselves in the local network (mDNS/avahi/zeroconf). One can trigger such an advertisement by broadcasting a QU question for spotify connect devices. The TXT record in the DNS answer packet contains the URL path of the device, at which a JSON endpoint is available for configuration. The getInfo action will return some basic information about the device, and addUser is used to hand over the user name, a blob (bearer token?) and a client key (see this gist). The thin client can use these to logon to the Spotify services.

The official Spotify clients list locally discovered Spotify Connect devices immediately. I assume that remote clients will see these devices only after these devices logged on to Spotify. I don't think a local full client registers a local thin client. I wonder however, what happens exactly when I make my Connect speaker at home, in standby mode, play a song using my smartphone over 3G. Does it remember the username, blob and clientKey from last time? Or is it constantly pinging Spotify and never really offline in standby mode?

(Standby = speaker available for Connect / Bluetooth, as opposed to soft-off, in which it is not available, but can be turned on again by pressing the power button of the device. Hard-off = power plug pulled)

@plietar
Copy link
Owner Author

plietar commented Jan 2, 2016

Implemented by bead9da.
It works on OS X, and at least builds on Linux (avahi's compatibility layer is used).
I'm not sure about windows though.

@plietar plietar closed this as completed Jan 2, 2016
@herrernst
Copy link
Contributor

I've tried it on Linux and get this error (if I don't specify username/password), controlled by Spotify OS X app:

RUST_BACKTRACE=1 target/debug/main -a ./appkey -c /tmp/librespot -n devicename
*** WARNING *** The program 'main' uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=main>
[("action", "getInfo")]
[("action", "getInfo")]
[("action", "getInfo")]
[("action", "getInfo")]
[("action", "getInfo")]
[("action", "getInfo")]
[("action", "addUser"), ("userName", "redacted"), ...]
thread '<main>' panicked at 'Invalid AES key size.', /home/user/.cargo/registry/src/github.com-48ad6e4054423464/rust-crypto-0.2.34/src/aessafe.rs:365
stack backtrace:
   1: 0x54f2f6ff - sys::backtrace::tracing::imp::write::ha3277b13961b5d10ufu
   2: 0x54f3247b - panicking::default_handler::_<closure>::closure.42348
   3: 0x54f31ecf - panicking::default_handler::h0cc9e1dfe7cdbe74psy
   4: 0x54f1c813 - sys_common::unwind::begin_unwind_inner::h4db81a6fb28a37f837s
   5: 0x54e573db - sys_common::unwind::begin_unwind::h1309004184094757753
                at ../src/libstd/sys/common/unwind/mod.rs:227
   6: 0x54e5b147 - aessafe::create_round_keys::h6342859b09ad6adeI0a
                at /home/user/src/librespot/<std macros>:3
   7: 0x54e548db - aessafe::AesSafe128EncryptorX8::new::h74bdb8b45e71e8790Ia
                at /home/user/.cargo/registry/src/github.com-48ad6e4054423464/rust-crypto-0.2.34/src/aessafe.rs:260
   8: 0x54e5427f - aes::ctr::hdcaf576521efcdabFha
                at /home/user/.cargo/registry/src/github.com-48ad6e4054423464/rust-crypto-0.2.34/src/aes.rs:291
   9: 0x54c1092f - discovery::DiscoveryManager::add_user::ha36f419d2f058b5fVSb
                at src/discovery.rs:103
  10: 0x54c12bb3 - discovery::DiscoveryManager::run::ha5e2429a74d5c4b87Zb
                at src/discovery.rs:144
  11: 0x54b15e17 - main::h4dc515e6bbc2b066Xba
                at src/main.rs:97
  12: 0x54f319e3 - sys_common::unwind::try::try_fn::h5020604801038689432

Thanks for your great work!

@plietar
Copy link
Owner Author

plietar commented Jan 2, 2016

I've just pushed a fix. Does it work now ?
I'm quite surprised I didn't have this problem myself.

@herrernst
Copy link
Contributor

Works now, thanks so much!

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

3 participants