-
Notifications
You must be signed in to change notification settings - Fork 630
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
Certificate issues when connecting session in Android app #1399
Comments
I tested to compile against webpki-roots feature for all rustls dependency like such. That has made the certificate errors disappear, will putting a new feature flag to control using either webpki-roots or native-certs be a solution here? Still, even after the certificate errors went away, I still couldn't get Session to connect, all 6 APs seems to just return TryAnotherAP error every time I tried on Android, tested the webpki-roots branch on other platform and Sessions are connecting as expected, so I'm a little lost why this is the case, even verified that the Login packet sent to AP is identical (except for the few unique ID fields) but still no luck. |
I've not checked but isn't part of the login packet platform dependent? Lots of Spotify now works very differently on Android so it wouldn't be surprising that the same thing doesn't work there (anymore). You might be better off pretending to be x86 everywhere. I'm not convinced there's any benefit in us reporting the platform honestly, just more complexity. |
Yeah, I'm aware there are device dependent fields sent. Just for the heck of it, I spoofed the OS field to return Windows as well as CPU family to return X86_64 here, but that didn't work either, all 6 APs still errored with TryAnotherAP Logging the spoofed login packet before it was sent yields something like this on Android. ClientResponseEncrypted { login_credentials: MessageField(Some(LoginCredentials { username: None, typ: Some(AUTHENTICATION_SPOTIFY_TOKEN), auth_data: Some([token stuff]), special_fields: SpecialFields { unknown_fields: UnknownFields { fields: None }, cached_size: CachedSize { size: 0 } } })), account_creation: None, fingerprint_response: MessageField(None), peer_ticket: MessageField(None), system_info: MessageField(Some(SystemInfo { cpu_family: Some(CPU_X86_64), cpu_subtype: None, cpu_ext: None, brand: None, brand_flags: None, os: Some(OS_WINDOWS), os_version: None, os_ext: None, system_information_string: Some("librespot-6c2bf8c-FywWxfn6"), device_id: Some("d8c05d3c-a4fc-4be3-818d-e336f8cd064c"), special_fields: SpecialFields { unknown_fields: UnknownFields { fields: None }, cached_size: CachedSize { size: 0 } } })), platform_model: None, version_string: Some("librespot 0.6.0-dev"), appkey: MessageField(None), client_info: MessageField(None), special_fields: SpecialFields { unknown_fields: UnknownFields { fields: None }, cached_size: CachedSize { size: 0 } } } For comparison, running the same application on my host Windows machine results in basically same login packet below, excluding the unique IDs, even used the same access token. But somehow it does connect on Windows 😅 ClientResponseEncrypted { login_credentials: MessageField(Some(LoginCredentials { username: None, typ: Some(AUTHENTICATION_SPOTIFY_TOKEN), auth_data: Some([token stuff]), special_fields: SpecialFields { unknown_fields: UnknownFields { fields: None }, cached_size: CachedSize { size: 0 } } })), account_creation: None, fingerprint_response: MessageField(None), peer_ticket: MessageField(None), system_info: MessageField(Some(SystemInfo { cpu_family: Some(CPU_X86_64), cpu_subtype: None, cpu_ext: None, brand: None, brand_flags: None, os: Some(OS_WINDOWS), os_version: None, os_ext: None, system_information_string: Some("librespot-6c2bf8c-sG3VBtfO"), device_id: Some("eb421dc8-c417-4b55-aac2-fd97fc7234fb"), special_fields: SpecialFields { unknown_fields: UnknownFields { fields: None }, cached_size: CachedSize { size: 0 } } })), platform_model: None, version_string: Some("librespot 0.6.0-dev"), appkey: MessageField(None), client_info: MessageField(None), special_fields: SpecialFields { unknown_fields: UnknownFields { fields: None }, cached_size: CachedSize { size: 0 } } } On another note, the "arm64" comparison for cpu_family is actually supposed to be "aarch64" according to |
I have just noticed, even with certificate errors from using native-certs, the error is also TryAnotherAP. Does any sort of handshaking failure just makes the AP telling librespot to try another AP? Update: Spoofing all instance of unique values deriving from "android" made playback work. Now to bisect what being sent is causing spotify to reject the client... |
From fiddling around, I found that if the client_hello packet's platform is Spoofing just client_hello to send I'm just trying various things out currently and hoping it will stick. |
There will be a load of places to change it and stay consistent, including agent type in http requests etc. Their server can only know what you send it, pretending to be non-android should be possible. I've no experience running librespot on android. |
Do you think librespot should spoof Android devices as Linux desktop? It definitely does work but I'm not sure whether the maintainers will agree to spoofing the device details like such. I can create a PR if this is the approach that's to be taken. |
It seems a reasonable workaround if we can't find anyone to fix it properly. But if you want to try and fix it properly there might be info in the mega thread at #1308 or in the go/java ports of librespot or at https://github.com/3052/platform/blob/v1.4.9/spotify/spotify.go How did you obtain your access token?. |
Alright, will take a look through the ports / thread.
I'm getting them via rspotify, since librespot's oauth flow doesn't currently have a way for app integration (since it either listens on localhost, or ask for input from stdin), and won't work at all when using Android's client ID to perform oauth, where the redirect URI must be I generate the PKCE auth_url with the appropriate redirect_url like such using rspotify (scopes "streaming" only), then with a managed webview from flutter, I'm able to extract the Using the access token from rspotify, I'm able to stream playback as per normal on at least Windows/Linux (keymaster client ID), but no luck on Android (android client ID) |
We should fix the oauth limitations. Thanks for highlighting. |
I have created 2 PRs for making things work on Android again. Both PRs will need to get merged before librespot can stream on Android again. |
* feat: use webpki as rustls roots on non-desktop platforms Silently switch over to using `rustls-webpki` when building for target_os that is not Windows/Linux/Mac because `rustls-native-certs` doesn't support them. Ideally we should use `rustls-platform-verifier` as it's now the recommended crate even on `rustls-native-certs` repository, since it chooses the right implementation for the platform. But currently it doesn't seem like `hyper-proxy2` or `tokio-tungstenite` doesn't support them yet. * Fix "no native root CA certificates found" (#1399)
* fix: android Session::connect failure from TryAnotherAP It appears that a combination of `Platform::PLATFORM_ANDROID_ARM` and connecting with `Credentials::with_access_token` causes all AP to error TryAnotherAP * fix: getting api access token should respect client id If we are trying to get an access token from login5 using stored credentials, ie: from oauth flow, we should use the oauth's client ID, this matches with the semantics as described in `Login5Manager::auth_token` * fix: cpu_family arm64 should be aarch64 * Fix audio streaming on Android platform (#1399)
logcat looks something like this when trying to Session::connect
logcat
I'm suspecting we are hitting this issue, where rustls-native-certs doesn't actually support Android/IOS and instead recommends using
rustls-platform-verifier
instead.Relevant
rustls-native-certs
usage hereOriginally posted by @SilverMira in #1277 (comment)
A repro is available here. The app is tested to have working playback on Windows.
I couldn't verify the app to be working on Linux since WSL is giving Timed out errors (unsure whether it's just my WSL acting up).Turns out it's my WSL acting up with DNS queries failing, verified the same application works on linux too with playback.Relevant logic to librespot here, which is about the same as
examples/play.rs
The text was updated successfully, but these errors were encountered: