-
Notifications
You must be signed in to change notification settings - Fork 593
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Credentials with access token (oauth) #1309
Credentials with access token (oauth) #1309
Conversation
3dcbc9d
to
27b2b59
Compare
0d5cbed
to
530bafe
Compare
530bafe
to
6f46c7a
Compare
I pulled out the login5 stuff from here since it's not actually required to implement the oauth login flow. But I did leave in the |
6f46c7a
to
de2e7b3
Compare
Isn't required for token auth.
We might need this later if need to re-auth and original creds are no longer valid/available.
Sometimes there is also a username field returned with the token, but not always. It's nice to have but not needed (since we'll get it when we auth our session) and trying to extract it requires lots of boilerplate from the oauth lib. Let's keep it simple.
Provide a token with sufficient scopes or empty string to obtain new token. When obtaining a new token, use --token-port argument to specify the redirect port. Specify 0 to manually enter the auth code (headless). Re-arranged setup function so have session_config earlier for use with get_access_token().
I've just tested this, unfortunately your example also exits with
also (I'm new to rust so maybe this is wrong) I run into the following compile error and had to change your code to
|
If it mentions password then that's not using --token mode. Sorry about the bad compile, I was trying to improve it last night and then GitHub went down leaving it in a mess. I'll sort that out later hopefully |
anyway thanks for your work! hope we get spotify working soon :) |
Oh, and yes sorry, you meant the actual example. Yes, that still needs updating. I was only using that for testing (before they deprecated password). Thank you for trying it though. I've had very little feedback otherwise. |
As I understood your code, the regarding the OAuth way, does every user need to register a client?! or do we fake/emulate the spotify app and force spotify to redirect to localhost? |
We can keep using Spotify's desktop client ID and either pop in our own redirect Uri and do it like them, or not bother and just have the redirect fail (harmless) but then the user has to manually provide the Auth code back to our code somehow. If you run librespot in this PR you can see both modes:
And
Yes, the redirect host has to be 127.0.0.1 when using their client ID. Anything else errors. If you do want to use your own client ID then that's also possible (not exposed in this PR) but then you've got to alter the scopes since it appears some of the ones they're using are not universally available. I don't know if the scopes you ask for here beyond 'streaming' actually matter, and how they impact what you can later request an access token for. E.g. if I Auth the session with just 'streaming' scope, can I later get an access token for more scopes? Presumably not but I have not tested |
ohhh nice thanks for the hint it seems that
works as expected! it simulates a spotify desktop app and recieves the token - thanks for this! |
Tried it on a Raspberry Pi 5 with cargo 1.80.1 and it worked like a charm! |
7d776cc
to
bf8b003
Compare
This is in a better state now. Still zero tests (sorry, World) but One bit I still don't like is my Arguably all the newer token stuff in core could be pulled out into a useful standalone crate but I don't quite see the point (yet). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found two more unwraps, if you could fix those?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even with tests! Perfect 😁
Perfect. I am going to merge this now. I don't have time for a release this weekend, so let's target next week for that. That leaves room coming days to give this a good shake-down, and putting in any last-minute PRs. There are a couple of almost-finished good PRs in there, would be nice if they could get polished in time for release. |
Wow, is there a detailed document about how to use this for now? |
Okay, a quick note for users who is feeling confusing about this: OAuth AuthenticationPassword login has been deprecated and is no longer supported. Instead, OAuth authentication must be used. Follow the steps below to authenticate using OAuth:
Good luck. |
I'll update the wiki and any other documentation I can find regarding auth. I need to somehow clarify this is different between what's released and what's in dev, confusion is probably inevitable for a while... sorry about that. I might leave some for posterity (clearly marked as deprecated). Regarding point 2 above, i don't believe there's anything fundamentally sensitive in that URL, particularly as we're using Spotify's client ID which is easy to discover and use. But you raise a great point and there is sensitive info in the trace messages that follow as it displays the secret token values. When I was developing this I found that detail invaluable, but now there's an example in the oauth module which can provide the same detail, so we could redact the logging here. For point 4, there's an alternate mode for this situation where instead of spawning a server to accept the response URI, librespot instead prompts you to manually enter that response URI. This means you can complete the oauth dance on your local machine and when the redirect fails (because nothing is listening on your local machine), just copy and paste the URL into librespot's prompt. There's a few ways to activate this mode, the easiest is to use option Edit: maybe something like |
Hi @kingosticks, First of all: thanks for your work! I think that everyone running Librespot was waiting for this to fix the authentication stuff. With respect to 4: would it also be an idea to be able to provide the redirect url manually? I'm aware that the user then has the responsibility to provide the correct one of course, but for the 'remote' situation this might be nice... Anyways, again thanks for fixing the authentication! |
Question: everything is working, except that I can't see/find where the token is stored for the next time. So right now I need to repeat the procedure whenever I start librespot. |
With the exception of the port, there isn't actually a choice when it comes to what redirect Uri to use, it has to match what's registered for the particular client ID being used. I think The token isn't stored. The token is exchanged for Spotify stored credentials, which are then saved in the cache folder as usual. You should run with |
@roderickvd what do you think about making the the system-cache enabled by default in 0.5? Having to do the oauth flow every time is bonkers and it shouldn't be the default. Personally I'd go the whole hog and have all caching enabled by default.. anyone who cares should be able to handle the change. And those that don't care can enjoy better performance. But I don't want to have a big discussion on the data cache here, I'll make a new issue if there's interest in that part. |
@kingosticks What about print a large warning when cache directory is not available to make users aware of what are they doing? |
Makes sense to me, to enable it by default. Would you put in a change? |
@kingosticks Challenge for me is that I provide Librespot as part of an appliance (RoPieee) that does not require any kind of (linux) knowledge to get things rolling. And right now I don't have a clue how to create an authorization feature that's still relatively easy to do for non-geeks like us... I tried this by creating a small reverse proxy and change the port number of the redirect uri... but that fails. The redirection and all works, but I get an error message from Librespot. Maybe I'm overlooking something here (or I'm misunderstanding things), but I appreciate your thoughts on this... |
Ideally your users would be able to copy and paste the failing redirect Uri into whatever admin console you presumably already have. You can then start librespot with Otherwise, reimplement the oauth handler on your own domain with your own client ID, request streaming scope, and display the resulting access token for the user to then paste into your admin console as above. A lot more hassle for a less ugly flow, but still essentially copying something from one window to another. This also requires you to get your own Spotify client ID and last time I checked, Spotify were hopeless at approving these. Or maybe your users can auth using Spotify connect? Ideally we'd be able to provide the device flow but I don't know if anyone reversing this https://community.spotify.com/t5/Spotify-for-Developers/Device-Authorization-Grant-authentication-flow-for-custom/td-p/5485468 |
Just an idea: I was sort of able to hijack the redirect by spawning a WebView of my control to the oauth url and listening for navigation to the callback url, this works even if callback urls are custom protocol like spotify-auth:// on android. This depends if you have your own "frontend" configuration app though |
That works because you are listening for the redirect on the same machine where the redirect is happening. In the headless case, you simply cannot do that with just a browser on the user's machine. It should also go without stating that that ssh forwarding etc would also be non-starters. Maybe we should start a dedicated discussion on this topic. |
I've been thinking more about this and I'm less opinionated now, to the point I'm not going to bother. To have it default enabled you need a default location. Could be the cwd or could be the XDG dir. Then you need the (existing) option to specify somewhere else and a new option to disable it entirely. And that's got to play nice with the general cache directory too. This is all more work and it's not interesting work to me, I've enough boring work to do as it is. I'll add a warning as suggested, and be done with it. |
I don't know if this oauth stuff really belongs in core, it doesn't feel quite right there so I added a new module. That new module could be useful standalone so it makes sense. If someone wants to take this and do something else that is fine by me.
This also leaves the token stuff a bit messy. We now provide two ways to get an access token:
session.token_provider().get_token("your,scopes")
using keymaster (Mercury)session.spclient().auth_token()
using login5 (HTTP)Both methods work (for session auth and playback) when you authenticate your session using a password or stored credentials. However, method 1 doesn't work when you authenticate your session using a spotify token (obtained using either method).
I think we want to get rid of this annoying pitfall. We could:
a) Get rid of method 1 altogether
b) Method 1 use method 2 under the hood
c) Change session authentication so when stored-creds are not used, it auths to obtain them and then re-auths using them.
Fixes #1308