mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Add client-token
header to spclient
requests
- Also fix an overflow panic when a token cannot be parsed. - Getting tokens always requires the keymaster client ID; passing the actual client ID yields a HashCash challenge.
This commit is contained in:
parent
ebfe8ca36c
commit
cdf84925ad
3 changed files with 12 additions and 6 deletions
|
@ -2,7 +2,7 @@ use std::{fmt, path::PathBuf, str::FromStr};
|
|||
|
||||
use url::Url;
|
||||
|
||||
const KEYMASTER_CLIENT_ID: &str = "65b708073fc0480ea92a077233ca87bd";
|
||||
pub const KEYMASTER_CLIENT_ID: &str = "65b708073fc0480ea92a077233ca87bd";
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SessionConfig {
|
||||
|
|
|
@ -9,7 +9,7 @@ use futures_util::future::IntoStream;
|
|||
use http::header::HeaderValue;
|
||||
use hyper::{
|
||||
client::ResponseFuture,
|
||||
header::{ACCEPT, AUTHORIZATION, CONTENT_ENCODING, CONTENT_TYPE, RANGE},
|
||||
header::{HeaderName, ACCEPT, AUTHORIZATION, CONTENT_ENCODING, CONTENT_TYPE, RANGE},
|
||||
Body, HeaderMap, Method, Request,
|
||||
};
|
||||
use protobuf::Message;
|
||||
|
@ -19,6 +19,7 @@ use thiserror::Error;
|
|||
use crate::{
|
||||
apresolve::SocketAddress,
|
||||
cdn_url::CdnUrl,
|
||||
config::KEYMASTER_CLIENT_ID,
|
||||
error::ErrorKind,
|
||||
protocol::{
|
||||
canvaz::EntityCanvazRequest,
|
||||
|
@ -40,6 +41,9 @@ component! {
|
|||
|
||||
pub type SpClientResult = Result<Bytes, Error>;
|
||||
|
||||
#[allow(clippy::declare_interior_mutable_const)]
|
||||
const CLIENT_TOKEN: HeaderName = HeaderName::from_static("client-token");
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SpClientError {
|
||||
#[error("missing attribute {0}")]
|
||||
|
@ -116,7 +120,7 @@ impl SpClient {
|
|||
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_id(KEYMASTER_CLIENT_ID.to_string());
|
||||
client_data.set_client_version(version::SEMVER.to_string());
|
||||
|
||||
let connectivity_data = client_data.mut_connectivity_sdk_data();
|
||||
|
@ -287,6 +291,7 @@ impl SpClient {
|
|||
.token_provider()
|
||||
.get_token("playlist-read")
|
||||
.await?;
|
||||
let client_token = self.client_token().await?;
|
||||
|
||||
let headers_mut = request.headers_mut();
|
||||
if let Some(ref hdrs) = headers {
|
||||
|
@ -296,6 +301,7 @@ impl SpClient {
|
|||
AUTHORIZATION,
|
||||
HeaderValue::from_str(&format!("{} {}", token.token_type, token.access_token,))?,
|
||||
);
|
||||
headers_mut.insert(CLIENT_TOKEN, HeaderValue::from_str(&client_token)?);
|
||||
|
||||
last_response = self.session().http_client().request_body(request).await;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use std::time::{Duration, Instant};
|
|||
use serde::Deserialize;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::Error;
|
||||
use crate::{config::KEYMASTER_CLIENT_ID, Error};
|
||||
|
||||
component! {
|
||||
TokenProvider : TokenProviderInner {
|
||||
|
@ -65,7 +65,7 @@ impl TokenProvider {
|
|||
|
||||
// scopes must be comma-separated
|
||||
pub async fn get_token(&self, scopes: &str) -> Result<Token, Error> {
|
||||
let client_id = self.session().client_id();
|
||||
let client_id = KEYMASTER_CLIENT_ID;
|
||||
if client_id.is_empty() {
|
||||
return Err(Error::invalid_argument("Client ID cannot be empty"));
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ impl Token {
|
|||
}
|
||||
|
||||
pub fn is_expired(&self) -> bool {
|
||||
self.timestamp + (self.expires_in - Self::EXPIRY_THRESHOLD) < Instant::now()
|
||||
self.timestamp + (self.expires_in.saturating_sub(Self::EXPIRY_THRESHOLD)) < Instant::now()
|
||||
}
|
||||
|
||||
pub fn in_scope(&self, scope: &str) -> bool {
|
||||
|
|
Loading…
Reference in a new issue