Retrieve client token (not working)

This commit is contained in:
Roderick van Domburg 2022-01-22 23:17:10 +01:00
parent 0630586cd6
commit 1528292583
No known key found for this signature in database
GPG key ID: FE2585E713F9F30A
4 changed files with 74 additions and 9 deletions

View file

@ -5,7 +5,7 @@ use futures_util::future::IntoStream;
use http::header::HeaderValue; use http::header::HeaderValue;
use hyper::{ use hyper::{
client::ResponseFuture, client::ResponseFuture,
header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE, RANGE}, header::{ACCEPT, AUTHORIZATION, CONTENT_ENCODING, CONTENT_TYPE, RANGE},
Body, HeaderMap, Method, Request, Body, HeaderMap, Method, Request,
}; };
use protobuf::Message; use protobuf::Message;
@ -17,16 +17,19 @@ use crate::{
cdn_url::CdnUrl, cdn_url::CdnUrl,
error::ErrorKind, error::ErrorKind,
protocol::{ protocol::{
canvaz::EntityCanvazRequest, connect::PutStateRequest, canvaz::EntityCanvazRequest,
clienttoken_http::{ClientTokenRequest, ClientTokenRequestType, ClientTokenResponse},
connect::PutStateRequest,
extended_metadata::BatchedEntityRequest, extended_metadata::BatchedEntityRequest,
}, },
Error, FileId, SpotifyId, version, Error, FileId, SpotifyId,
}; };
component! { component! {
SpClient : SpClientInner { SpClient : SpClientInner {
accesspoint: Option<SocketAddress> = None, accesspoint: Option<SocketAddress> = None,
strategy: RequestStrategy = RequestStrategy::default(), strategy: RequestStrategy = RequestStrategy::default(),
client_token: String = String::new(),
} }
} }
@ -88,6 +91,51 @@ impl SpClient {
Ok(format!("https://{}:{}", ap.0, ap.1)) Ok(format!("https://{}:{}", ap.0, ap.1))
} }
pub async fn client_token(&self) -> Result<String, Error> {
// TODO: implement expiry
let client_token = self.lock(|inner| inner.client_token.clone());
if !client_token.is_empty() {
return Ok(client_token);
}
let mut message = ClientTokenRequest::new();
message.set_request_type(ClientTokenRequestType::REQUEST_CLIENT_DATA_REQUEST);
let client_data = message.mut_client_data();
client_data.set_client_id(self.session().client_id());
client_data.set_client_version(version::SEMVER.to_string());
let connectivity_data = client_data.mut_connectivity_sdk_data();
connectivity_data.set_device_id(self.session().device_id().to_string());
let platform_data = connectivity_data.mut_platform_specific_data();
let windows_data = platform_data.mut_windows();
windows_data.set_os_version(10);
windows_data.set_os_build(21370);
windows_data.set_unknown_value_4(2);
windows_data.set_unknown_value_6(9);
windows_data.set_unknown_value_7(332);
windows_data.set_unknown_value_8(34404);
windows_data.set_unknown_value_10(true);
let body = protobuf::text_format::print_to_string(&message);
let request = Request::builder()
.method(&Method::POST)
.uri("https://clienttoken.spotify.com/v1/clienttoken")
.header(ACCEPT, HeaderValue::from_static("application/x-protobuf"))
.header(CONTENT_ENCODING, HeaderValue::from_static(""))
.body(Body::from(body))?;
let response = self.session().http_client().request_body(request).await?;
let response = ClientTokenResponse::parse_from_bytes(&response)?;
let client_token = response.get_granted_token().get_token().to_owned();
self.lock(|inner| inner.client_token = client_token.clone());
Ok(client_token)
}
pub async fn request_with_protobuf( pub async fn request_with_protobuf(
&self, &self,
method: &Method, method: &Method,
@ -100,7 +148,7 @@ impl SpClient {
let mut headers = headers.unwrap_or_else(HeaderMap::new); let mut headers = headers.unwrap_or_else(HeaderMap::new);
headers.insert( headers.insert(
CONTENT_TYPE, CONTENT_TYPE,
HeaderValue::from_static("application/protobuf"), HeaderValue::from_static("application/x-protobuf"),
); );
self.request(method, endpoint, Some(headers), Some(body)) self.request(method, endpoint, Some(headers), Some(body))
@ -132,6 +180,9 @@ impl SpClient {
let body = body.unwrap_or_else(String::new); let body = body.unwrap_or_else(String::new);
let client_token = self.client_token().await;
trace!("CLIENT TOKEN: {:?}", client_token);
loop { loop {
tries += 1; tries += 1;

View file

@ -17,6 +17,7 @@ fn compile() {
let files = &[ let files = &[
proto_dir.join("connect.proto"), proto_dir.join("connect.proto"),
proto_dir.join("connectivity.proto"),
proto_dir.join("devices.proto"), proto_dir.join("devices.proto"),
proto_dir.join("entity_extension_data.proto"), proto_dir.join("entity_extension_data.proto"),
proto_dir.join("extended_metadata.proto"), proto_dir.join("extended_metadata.proto"),
@ -26,6 +27,7 @@ fn compile() {
proto_dir.join("playlist_annotate3.proto"), proto_dir.join("playlist_annotate3.proto"),
proto_dir.join("playlist_permission.proto"), proto_dir.join("playlist_permission.proto"),
proto_dir.join("playlist4_external.proto"), proto_dir.join("playlist4_external.proto"),
proto_dir.join("spotify/clienttoken/v0/clienttoken_http.proto"),
proto_dir.join("storage-resolve.proto"), proto_dir.join("storage-resolve.proto"),
proto_dir.join("user_attributes.proto"), proto_dir.join("user_attributes.proto"),
// TODO: remove these legacy protobufs when we are on the new API completely // TODO: remove these legacy protobufs when we are on the new API completely

View file

@ -1,5 +1,3 @@
// Extracted from: Spotify 1.1.33.569 (Windows)
syntax = "proto3"; syntax = "proto3";
package spotify.clienttoken.data.v0; package spotify.clienttoken.data.v0;
@ -17,6 +15,7 @@ message PlatformSpecificData {
oneof data { oneof data {
NativeAndroidData android = 1; NativeAndroidData android = 1;
NativeIOSData ios = 2; NativeIOSData ios = 2;
NativeWindowsData windows = 4;
} }
} }
@ -36,6 +35,16 @@ message NativeIOSData {
string simulator_model_identifier = 5; string simulator_model_identifier = 5;
} }
message NativeWindowsData {
int32 os_version = 1;
int32 os_build = 3;
int32 unknown_value_4 = 4;
int32 unknown_value_6 = 6;
int32 unknown_value_7 = 7;
int32 unknown_value_8 = 8;
bool unknown_value_10 = 10;
}
message Screen { message Screen {
int32 width = 1; int32 width = 1;
int32 height = 2; int32 height = 2;

View file

@ -1,5 +1,3 @@
// Extracted from: Spotify 1.1.33.569 (Windows)
syntax = "proto3"; syntax = "proto3";
package spotify.clienttoken.http.v0; package spotify.clienttoken.http.v0;
@ -24,7 +22,7 @@ message ClientDataRequest {
string client_id = 2; string client_id = 2;
oneof data { oneof data {
data.v0.ConnectivitySdkData connectivity_sdk_data = 3; spotify.clienttoken.data.v0.ConnectivitySdkData connectivity_sdk_data = 3;
} }
} }
@ -42,10 +40,15 @@ message ClientTokenResponse {
} }
} }
message TokenDomain {
string domain = 1;
}
message GrantedTokenResponse { message GrantedTokenResponse {
string token = 1; string token = 1;
int32 expires_after_seconds = 2; int32 expires_after_seconds = 2;
int32 refresh_after_seconds = 3; int32 refresh_after_seconds = 3;
repeated TokenDomain domains = 4;
} }
message ChallengesResponse { message ChallengesResponse {