From Nov 2025 Spotify will require that the OAuth redirect is to a https url,
so we go via a Github hosted intermediate page.

Ref issue #1858
This commit is contained in:
ejurgensen 2025-05-03 23:31:24 +02:00
parent 216b6268c7
commit ae5be5f83e
5 changed files with 14 additions and 20 deletions

View File

@ -222,6 +222,8 @@ static cfg_opt_t sec_spotify[] =
// Issued by Spotify on developer.spotify.com for forked-daapd/OwnTone // Issued by Spotify on developer.spotify.com for forked-daapd/OwnTone
CFG_STR("webapi_client_id", "0e684a5422384114a8ae7ac020f01789", CFGF_NONE), CFG_STR("webapi_client_id", "0e684a5422384114a8ae7ac020f01789", CFGF_NONE),
CFG_STR("webapi_client_secret", "232af95f39014c9ba218285a5c11a239", CFGF_NONE), CFG_STR("webapi_client_secret", "232af95f39014c9ba218285a5c11a239", CFGF_NONE),
// Must be in allow-list on developer.spotify.com for forked-daapd/OwnTone
CFG_STR("redirect_uri", "https://owntone.github.io/owntone-oauth/spotify/", CFGF_NONE),
CFG_END() CFG_END()
}; };

View File

@ -1284,8 +1284,6 @@ jsonapi_reply_spotify(struct httpd_request *hreq)
CHECK_NULL(L_WEB, jreply = json_object_new_object()); CHECK_NULL(L_WEB, jreply = json_object_new_object());
#ifdef SPOTIFY #ifdef SPOTIFY
int httpd_port;
char redirect_uri[256];
char *oauth_uri; char *oauth_uri;
struct spotify_status sp_status; struct spotify_status sp_status;
struct spotifywebapi_status_info webapi_info; struct spotifywebapi_status_info webapi_info;
@ -1293,10 +1291,7 @@ jsonapi_reply_spotify(struct httpd_request *hreq)
json_object_object_add(jreply, "enabled", json_object_new_boolean(true)); json_object_object_add(jreply, "enabled", json_object_new_boolean(true));
httpd_port = cfg_getint(cfg_getsec(cfg, "library"), "port"); oauth_uri = spotifywebapi_oauth_uri_get();
snprintf(redirect_uri, sizeof(redirect_uri), "http://owntone.local:%d/oauth/spotify", httpd_port);
oauth_uri = spotifywebapi_oauth_uri_get(redirect_uri);
if (!oauth_uri) if (!oauth_uri)
{ {
DPRINTF(E_LOG, L_WEB, "Cannot display Spotify oauth interface (http_form_uriencode() failed)\n"); DPRINTF(E_LOG, L_WEB, "Cannot display Spotify oauth interface (http_form_uriencode() failed)\n");

View File

@ -43,15 +43,10 @@
static int static int
oauth_reply_spotify(struct httpd_request *hreq) oauth_reply_spotify(struct httpd_request *hreq)
{ {
char redirect_uri[256];
const char *errmsg; const char *errmsg;
int httpd_port;
int ret; int ret;
httpd_port = cfg_getint(cfg_getsec(cfg, "library"), "port"); ret = spotifywebapi_oauth_callback(hreq->query, &errmsg);
snprintf(redirect_uri, sizeof(redirect_uri), "http://owntone.local:%d/oauth/spotify", httpd_port);
ret = spotifywebapi_oauth_callback(hreq->query, redirect_uri, &errmsg);
if (ret < 0) if (ret < 0)
{ {
DPRINTF(E_LOG, L_WEB, "Could not parse Spotify OAuth callback '%s': %s\n", hreq->uri, errmsg); DPRINTF(E_LOG, L_WEB, "Could not parse Spotify OAuth callback '%s': %s\n", hreq->uri, errmsg);

View File

@ -150,6 +150,7 @@ static bool scanning;
// Endpoints and credentials for the web api // Endpoints and credentials for the web api
static const char *spotify_client_id; static const char *spotify_client_id;
static const char *spotify_client_secret; static const char *spotify_client_secret;
static const char *spotify_redirect_uri;
static const char *spotify_scope = "playlist-read-private playlist-read-collaborative user-library-read user-read-private streaming"; static const char *spotify_scope = "playlist-read-private playlist-read-collaborative user-library-read user-read-private streaming";
@ -574,7 +575,7 @@ request_user_info()
* @return 0 on success, -1 on failure * @return 0 on success, -1 on failure
*/ */
static int static int
token_get(const char *code, const char *redirect_uri, const char **err) token_get(const char *code, const char **err)
{ {
struct keyval kv = { 0 }; struct keyval kv = { 0 };
int ret; int ret;
@ -584,7 +585,7 @@ token_get(const char *code, const char *redirect_uri, const char **err)
(keyval_add(&kv, "code", code) == 0) && (keyval_add(&kv, "code", code) == 0) &&
(keyval_add(&kv, "client_id", spotify_client_id) == 0) && (keyval_add(&kv, "client_id", spotify_client_id) == 0) &&
(keyval_add(&kv, "client_secret", spotify_client_secret) == 0) && (keyval_add(&kv, "client_secret", spotify_client_secret) == 0) &&
(keyval_add(&kv, "redirect_uri", redirect_uri) == 0) ); (keyval_add(&kv, "redirect_uri", spotify_redirect_uri) == 0) );
if (!ret) if (!ret)
{ {
@ -2069,6 +2070,7 @@ spotifywebapi_library_init()
spotify_client_id = cfg_getstr(cfg_getsec(cfg, "spotify"), "webapi_client_id"); spotify_client_id = cfg_getstr(cfg_getsec(cfg, "spotify"), "webapi_client_id");
spotify_client_secret = cfg_getstr(cfg_getsec(cfg, "spotify"), "webapi_client_secret"); spotify_client_secret = cfg_getstr(cfg_getsec(cfg, "spotify"), "webapi_client_secret");
spotify_redirect_uri = cfg_getstr(cfg_getsec(cfg, "spotify"), "redirect_uri");
ret = spotify_init(); ret = spotify_init();
if (ret < 0) if (ret < 0)
@ -2139,7 +2141,7 @@ webapi_purge(void *arg, int *ret)
/* ------------------------------ Public API -------------------------------- */ /* ------------------------------ Public API -------------------------------- */
char * char *
spotifywebapi_oauth_uri_get(const char *redirect_uri) spotifywebapi_oauth_uri_get(void)
{ {
struct keyval kv = { 0 }; struct keyval kv = { 0 };
char *param; char *param;
@ -2150,7 +2152,7 @@ spotifywebapi_oauth_uri_get(const char *redirect_uri)
uri = NULL; uri = NULL;
ret = ( (keyval_add(&kv, "client_id", spotify_client_id) == 0) && ret = ( (keyval_add(&kv, "client_id", spotify_client_id) == 0) &&
(keyval_add(&kv, "response_type", "code") == 0) && (keyval_add(&kv, "response_type", "code") == 0) &&
(keyval_add(&kv, "redirect_uri", redirect_uri) == 0) && (keyval_add(&kv, "redirect_uri", spotify_redirect_uri) == 0) &&
(keyval_add(&kv, "scope", spotify_scope) == 0) && (keyval_add(&kv, "scope", spotify_scope) == 0) &&
(keyval_add(&kv, "show_dialog", "false") == 0) ); (keyval_add(&kv, "show_dialog", "false") == 0) );
if (!ret) if (!ret)
@ -2178,7 +2180,7 @@ spotifywebapi_oauth_uri_get(const char *redirect_uri)
} }
int int
spotifywebapi_oauth_callback(struct evkeyvalq *param, const char *redirect_uri, const char **errmsg) spotifywebapi_oauth_callback(struct evkeyvalq *param, const char **errmsg)
{ {
const char *code; const char *code;
char *user = NULL; char *user = NULL;
@ -2196,7 +2198,7 @@ spotifywebapi_oauth_callback(struct evkeyvalq *param, const char *redirect_uri,
DPRINTF(E_DBG, L_SPOTIFY, "Received OAuth code: %s\n", code); DPRINTF(E_DBG, L_SPOTIFY, "Received OAuth code: %s\n", code);
ret = token_get(code, redirect_uri, errmsg); ret = token_get(code, errmsg);
if (ret < 0) if (ret < 0)
goto error; goto error;

View File

@ -43,9 +43,9 @@ struct spotifywebapi_access_token
char * char *
spotifywebapi_oauth_uri_get(const char *redirect_uri); spotifywebapi_oauth_uri_get(void);
int int
spotifywebapi_oauth_callback(struct evkeyvalq *param, const char *redirect_uri, const char **errmsg); spotifywebapi_oauth_callback(struct evkeyvalq *param, const char **errmsg);
void void
spotifywebapi_fullrescan(void); spotifywebapi_fullrescan(void);