Skip to content

Commit

Permalink
Merge pull request #20 from Sycrosity/spotify-auth
Browse files Browse the repository at this point in the history
spotify auth
  • Loading branch information
Sycrosity authored Aug 13, 2024
2 parents b9c011e + 3c2d528 commit 8694337
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"name": "Wokwi GDB",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/target/xtensa-esp32-none-elf/release/cansat",
"program": "${workspaceFolder}/target/xtensa-esp32-none-elf/release/teeny",
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"miDebuggerPath": "${userHome}/.espressif/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-gdb",
Expand Down
4 changes: 4 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ fn main() -> Result<(), Box<dyn Error>> {
"cargo::rustc-env=PASSWORD={}",
std::env::var("PASSWORD").unwrap_or_default()
);
println!(
"cargo::rustc-env=CLIENT_ID={}",
std::env::var("CLIENT_ID").unwrap_or_default()
);

Ok(())
}
31 changes: 31 additions & 0 deletions src/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::prelude::*;

#[derive(Debug)]
pub struct AuthParams {
pub response_type: &'static str,
pub client_id: &'static str,
pub scope: &'static str,
pub code_challenge: String<64>,
pub code_challenge_method: &'static str,
pub redirect_uri: &'static str,
}

impl AuthParams {
pub fn to_string(&self) -> String<256> {
let mut query_string = String::new();
query_string.push_str("?").unwrap();
query_string.push_str("response_type=").unwrap();
query_string.push_str(self.response_type).unwrap();
query_string.push_str("&client_id=").unwrap();
query_string.push_str(self.client_id).unwrap();
query_string.push_str("&scope=").unwrap();
query_string.push_str(self.scope).unwrap();
query_string.push_str("&code_challenge=").unwrap();
query_string.push_str(self.code_challenge.as_str()).unwrap();
query_string.push_str("&code_challenge_method=").unwrap();
query_string.push_str(self.code_challenge_method).unwrap();
query_string.push_str("&redirect_uri=").unwrap();
query_string.push_str(self.redirect_uri).unwrap();
query_string
}
}
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![no_std]
#![no_main]
#![feature(impl_trait_in_assoc_type)]
#![feature(type_alias_impl_trait)]
#![feature(error_in_core)]
#![allow(clippy::unused_unit)]
Expand All @@ -12,6 +13,7 @@ pub mod blink;
pub mod display;
pub mod errors;

pub mod auth;
pub mod buttons;
pub mod logger;
#[cfg(feature = "net")]
Expand All @@ -22,7 +24,9 @@ pub mod volume;
pub mod prelude {

pub const SSID: &str = env!("SSID");

pub const PASSWORD: &str = env!("PASSWORD");
pub const CLIENT_ID: &str = env!("CLIENT_ID");

pub use core::f64::consts::PI;

Expand Down Expand Up @@ -55,6 +59,7 @@ pub mod prelude {

pub static RNG: StaticCell<Rng> = StaticCell::new();

pub use base64::prelude::*;
pub use embassy_executor::task;
pub use embassy_time::{Delay, Duration, Instant, Ticker, Timer};
#[allow(unused)]
Expand Down
106 changes: 86 additions & 20 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#![feature(impl_trait_in_assoc_type)]

// use base64::{prelude::*, Engine};
use embassy_executor::Spawner;
use embassy_net::{
dns::DnsSocket,
tcp::client::{TcpClient, TcpClientState},
tcp::{
client::{TcpClient, TcpClientState},
TcpSocket,
},
Config, Ipv4Address, Ipv4Cidr, Stack, StackResources, StaticConfigV4,
};
use embassy_time::Ticker;
Expand All @@ -17,20 +20,22 @@ use esp_hal::{
peripherals::{Peripherals, ADC1},
rng::Rng,
sha::{Sha, ShaMode},
timer::timg::TimerGroup,
timer::{OneShotTimer, PeriodicTimer},
};
use esp_println::println;
use reqwless::{
client::{HttpClient, TlsConfig, TlsVerify},
request::{Method, RequestBuilder},
};
use static_cell::make_static;
use teeny::{
auth::AuthParams,
blink::blink,
buttons::{
display_play_pause, display_skip, publish_play_pause, publish_raw_skip, publish_skip,
},
display::{display_shapes, screen_counter},
net::{ap_task, connection, wifi_task},
net::{ap_task, connection, random_utf8, wifi_task},
prelude::*,
volume::{display_volume, publish_volume},
};
Expand Down Expand Up @@ -67,9 +72,9 @@ async fn main(spawner: Spawner) -> ! {
let mut rng = *RNG.init(rng);

#[cfg(target_arch = "riscv32")]
let _hasher = Sha::new(peripherals.SHA, ShaMode::SHA256, None);
let mut sha = Sha::new(peripherals.SHA, ShaMode::SHA256, None);
#[cfg(target_arch = "xtensa")]
let _hasher = Sha::new(peripherals.SHA, ShaMode::SHA256);
let mut sha = Sha::new(peripherals.SHA, ShaMode::SHA256);

#[cfg(target_arch = "xtensa")]
let pot_pin = adc1_config.enable_pin(io.pins.gpio32, Attenuation::Attenuation11dB);
Expand Down Expand Up @@ -196,47 +201,108 @@ async fn main(spawner: Spawner) -> ! {
.spawn(display_play_pause(I2cDevice::new(i2c_bus)))
.ok();

loop {
info!("Starting wifi loop...");
let mut ap_rx_buffer = [0; 1536];
let mut ap_tx_buffer = [0; 1536];

let mut ap_socket = TcpSocket::new(ap_stack, &mut ap_rx_buffer, &mut ap_tx_buffer);

ap_socket.set_timeout(Some(embassy_time::Duration::from_secs(10)));

let mut wifi_rx_buf = [0; 16640];
let mut wifi_tx_buf = [0; 16640];

let mut rx_buf = [0; 16640];
let mut tx_buf = [0; 16640];
let state = TcpClientState::<1, 4096, 4096>::new();

let state = TcpClientState::<1, 4096, 4096>::new();
let tcp_client = TcpClient::new(wifi_stack, &state);

let tcp_client = TcpClient::new(wifi_stack, &state);
let dns_socket = DnsSocket::new(wifi_stack);

let dns_socket = DnsSocket::new(wifi_stack);
let config = TlsConfig::new(seed, &mut wifi_rx_buf, &mut wifi_tx_buf, TlsVerify::None);

let config = TlsConfig::new(seed, &mut rx_buf, &mut tx_buf, TlsVerify::None);
let mut client = HttpClient::new_with_tls(&tcp_client, &dns_socket, config);

let mut client = HttpClient::new_with_tls(&tcp_client, &dns_socket, config);
debug!("Http Client created");

debug!("HttpClient created");
loop {
info!("Starting wifi loop...");

let code_challenge_raw = random_utf8::<64>(rng);

// convert the vec to a string
// SAFETY: the verifier is guaranteed to be valid utf8 as it is base64 encoded
let code_challenge: String<64> = String::from_utf8(
Vec::from_slice(&code_challenge_raw)
.expect("should be enough bytes for cloning into the vec"),
)
.expect("Base64 encoding is valid utf8");

let token = "TOKEN_GOES_HERE";

let mut string: String<64> = String::new();

string.push_str("Bearer ").unwrap();
string.push_str(token).unwrap();
let mut code_challenge_raw = code_challenge_raw.as_slice();

// SHA256 Hashing the verifier
while !code_challenge_raw.is_empty() {
// SAFETY: All the HW Sha functions are infallible so unwrap is fine to use if
// you use block!
code_challenge_raw = block!(sha.update(code_challenge_raw)).unwrap();
}

let mut hash_buffer: [u8; 32] = [0; 32];

block!(sha.finish(hash_buffer.as_mut_slice())).unwrap();

let mut base64_buf: Vec<u8, 47> = Vec::new();
base64_buf.resize(32 * 4 / 3 + 4, 0).unwrap();

// Encode the hash to base64
let real_b64_len = BASE64_STANDARD_NO_PAD
.encode_slice(hash_buffer, &mut base64_buf)
.unwrap();

base64_buf.truncate(real_b64_len);

let _verifier_hash = String::from_utf8(base64_buf).unwrap();

let auth_params = AuthParams {
response_type: "code",
client_id: CLIENT_ID,
scope: "user-read-private%20user-read-email",
code_challenge,
code_challenge_method: "S256",
redirect_uri: "http://192.168.2.1/callback",
};

let headers = [
("User-Agent", "teeny/0.1.0"),
("Accept", "*/*"),
("Connection", "close"),
("Authorization", string.as_str()),
];

let mut header_buf = [0; 1024];
let mut header_buf = [0; 1024 * 8];

let mut auth_path: String<512> = String::new();

auth_path.push_str("/authorize").unwrap();
auth_path
.push_str(auth_params.to_string().as_str())
.inspect_err(|e| println!("{e:?}"))
.unwrap();

println!("{:#?}", &auth_path);

let mut request = client
.request(Method::GET, "https://example.com")
.request(Method::GET, "https://accounts.spotify.com")
.await
.unwrap()
.path("/v1/artists/0TnOYISbd1XYRBk9myaseg")
.path(&auth_path)
.headers(&headers);

// println!("{:#?}", &request.build());

let response = request.send(&mut header_buf).await.unwrap();

debug!("Request sent");
Expand Down

0 comments on commit 8694337

Please sign in to comment.