From 128ca7cb2eb3cc9c363a058aa2a4933efa91fc14 Mon Sep 17 00:00:00 2001 From: Elias Assaf Date: Fri, 4 Jul 2025 14:56:54 +0300 Subject: [PATCH] feat(auth): Automatically find free port * feat: add auth_port configuration option Signed-off-by: Elias Assaf * feat(auth): Automatically find free port --------- Signed-off-by: Elias Assaf Co-authored-by: Henrik Friedrichsen --- CHANGELOG.md | 4 ++++ src/authentication.rs | 19 +++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9474603..bd6b2d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Automatically find free port for OAuth2 login flow + ### Fixed - Skip unplayable tracks diff --git a/src/authentication.rs b/src/authentication.rs index f26b6de..dc3dfa0 100644 --- a/src/authentication.rs +++ b/src/authentication.rs @@ -1,3 +1,5 @@ +use std::net::TcpListener; + use librespot_core::authentication::Credentials as RespotCredentials; use librespot_core::cache::Cache; use librespot_oauth::get_access_token; @@ -7,7 +9,6 @@ use crate::config::{self, Config}; use crate::spotify::Spotify; pub const SPOTIFY_CLIENT_ID: &str = "65b708073fc0480ea92a077233ca87bd"; -pub const CLIENT_REDIRECT_URI: &str = "http://127.0.0.1:8989/login"; static OAUTH_SCOPES: &[&str] = &[ "playlist-modify", @@ -35,6 +36,20 @@ static OAUTH_SCOPES: &[&str] = &[ "user-top-read", ]; +pub fn find_free_port() -> Result { + let socket = TcpListener::bind("127.0.0.1:0").map_err(|e| e.to_string())?; + socket + .local_addr() + .map(|addr| addr.port()) + .map_err(|e| e.to_string()) +} + +pub fn get_client_redirect_uri() -> String { + let auth_port = find_free_port().expect("Could not find free port"); + let redirect_url = format!("http://127.0.0.1:{auth_port}/login"); + redirect_url +} + /// Get credentials for use with librespot. This first tries to get cached credentials. If no cached /// credentials are available it will initiate the OAuth2 login process. pub fn get_credentials(configuration: &Config) -> Result { @@ -73,7 +88,7 @@ pub fn create_credentials() -> Result { println!("To login you need to perform OAuth2 authorization using your web browser\n"); get_access_token( SPOTIFY_CLIENT_ID, - CLIENT_REDIRECT_URI, + &get_client_redirect_uri(), OAUTH_SCOPES.to_vec(), ) .map(|token| RespotCredentials::with_access_token(token.access_token))