mirror of
https://github.com/sigma67/ytmusicapi.git
synced 2026-04-26 07:46:00 +03:00
[GH-ISSUE #376] OAuth doesn't work with arbitrary file names #295
Labels
No labels
a/b
bug
documentation
enhancement
good first issue
help wanted
invalid
pull-request
question
wontfix
yt-error
yt-update
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/ytmusicapi#295
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @benblank on GitHub (Apr 10, 2023).
Original GitHub issue: https://github.com/sigma67/ytmusicapi/issues/376
Originally assigned to: @sigma67 on GitHub.
Describe the bug
When creating a
YTMusicinstance with OAuth credentials from a file not named "oauth.json" (or rather, the provided path to which does not contain the string "oauth.json"), the resulting instance cannot successfully connect to YouTube Music. Worse, the resulting error (a complaint from therequestslibrary that a header is of the wrong type) doesn't provide any information which helps identify the actual problem (the authentication data being interpreted as invalid browser auth) unless one reads theytmusicapisource.To Reproduce
Steps to reproduce the error:
Make and enter a new, empty directory.
python3 -m venv .venv. .venv/bin/activatepip3 install ytmusicapiytmusicapi oauthFollow the instructions as usual to create "oauth.json".
mv oauth.json oauth-foo.json← And here's the problem, folks. 🙂Create a new file "example.py" with the following contents:
python3 example.pyObserve the resulting
InvalidHeaderexception complaining that the value of the "expires_in" header should be a string or bytes object.Additional context
I ran into this because I'm trying to migrate some data between two accounts, so naively renamed the files created by
ytmusicapi oauthto "oauth-.json".Possible solution
(Note that I'd be happy to submit a PR for this; I'd create it now, but I need to step away from the keyboard for a bit.)
Looking at the source of the
prepare_headersfunction, I see that it's detecting whether to use OAuth by examining the file's name; I think it would be less surprising to base it on the contents, instead.This could be done, for example, by checking for the presence of a key which is required to be present when using OAuth but is unlikely to be found in the headers used for browser authentication or by checking whether "expires_at" or "expires_in" keys are present and have have an integer value, as integers aren't valid header values.
Alternatively,
input_jsoncould simply be assumed to contain OAuth data (optimistically trying to create aYTMusicOAuthinstance), with a fallback to browser authentication if aKeyErroris thrown.YTMusicOAuth.load_headersappears to require that the keys "access_token", "expires_at", "refresh_token", and "token_type" all be present; it seems very unlikely that all four would be found in a browser's request headers, as none of them are standard HTTP headers.@sigma67 commented on GitHub (Apr 10, 2023):
Yes, I didn't really see a probably with mandating a specific filename. But I suppose it's more flexible to allow any filename, as it's being passed in through the constructor.
Regarding an implementation, I think we should implement some validation for the files. For browser-based auth, we can rely on the presence of the
Cookievalue, while foroauththe following are mandatory:token_type,access_token,refresh_tokenandexpires_at.@sigma67 commented on GitHub (Apr 10, 2023):
For validation, create functions in auth/browser.py and auth/oauth.py to separate that logic from the ytmusic.py file.
For browser validation we should reuse the existing logic:
github.com/sigma67/ytmusicapi@defb621407/ytmusicapi/ytmusic.py (L105-L112)@benblank commented on GitHub (Apr 19, 2023):
Yes! Sorry, I've had a bit less time than expected, but I'm very much working on it.
Basically, I was finding it awkward to track the different types of authentication (none, browser, OAuth) and handle them consistently with the logic being spread out, so I'm doing some minor refactoring to centralize it for each type. I'll try to get a draft PR up later today with an example of what I'm talking about, so that you can actually visualize it. 😉