hakko / subsonic

A streaming music server. Based on Subsonic, with MusicCabinet integration.
34 stars 20 forks source link

Better detection of last.fm callback URL #32

Open ties opened 11 years ago

ties commented 11 years ago

At the moment the LastFmSettingsController creates a callback URL that might not work in some situations. For example, when SubSonic is behind a reverse proxy, it might create a callback referring to localhost.

The real solution is to fix the reverse proxy setup, ie:

        ProxyPreserveHost On
        <Location />
                ProxyPass http://localhost:4040/ retry=5
                ProxyPassReverse http://localhost:4040/

                …
        </Location>

However, re-using the approach used by net.sourceforge.subsonic.service.ShareService#getShareBaseUrl should provide the behavior the user expects, except in the situation where the local hostname is not a global hostname (i.e. when using a lan-only name).

This pull request contains a (quick) implementation callback url detection based on the strategry used by ShareService. However, when no setting is found it uses the complete request URL as fallback instead of trying to detect the hostname.

I hope it fully works – I was not able to test the situation where subsonic is reachable using a *.subsonic.com name.

hakko commented 11 years ago

Thanks for finding that unfinished piece of code and coming up with a solution for it! I do like your addition, however, I have one objection:

If I have either a share URL or a Subsonic redirection URL specified in the settings, but I access the server locally as localhost:port/subsonic, the callback URL domain will differ from where I'm actually logged in. For example, if I use xxx.subsonic.org as a redirection URL for my friends, but I log in myself to localhost:port/subsonic to configure a last.fm account while at home, last.fm will send me back to xxx.subsonic.org which redirects to my actual IP number, where my session (from localhost) is not valid, taking me back to the log in screen. Basically forcing me to log in again, go back to the settings, and redo the authentication procedure.

Maybe this is a corner case but I figure that is not totally uncommon? This is the original reason I just left it as request.getRequestURL(). Do you have a good idea on how to detect that scenario compared to the reverse proxy one?

ties commented 11 years ago

I realized there was a issue where the user was redirected to the actual server but with a different URL – and thus a different session. However I did not realize that it is a common use case.

I do not know a server-side method to distinguish the badly configured reverse-proxy from the local server case.

The best server-side solution that I can think off is using Spring Security to generate and accept one-time authentication tokens that only have a role for the LastFmSettingsController's callback URL.

In my opinion the best behaving solution is to get the used URL in the browser using javascript.

Since the SubSonic last.fm API secret is on Github, I want to be careful with security. However, this case is very similar to the current situation where the callback URL is in the page source. Can you think of any?