tokland / youtube-upload

Upload videos to Youtube from the command line
2.06k stars 464 forks source link

Google's deprecation of out-of-band oauth flow #349

Open zougloub opened 2 years ago

zougloub commented 2 years ago

I hadn't uploaded youtube videos in a while and had issues when doing it today.

Google has obsoleted the oauth flow used in youtube-upload: https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html#instructions-oob

The following change in auth/__init__.py, along with creation of a OAuth 2.0 Client ID for a web application, with an arbitrary callback URL, on https://console.cloud.google.com/apis/credentials helps:

-    flow.redirect_uri = oauth2client.client.OOB_CALLBACK_URN
+    flow.redirect_uri = "https://oauth2callback.uri" # or anything else

I just copied the code from the browser address bar, into the youtube-upload code prompt, and youtube-upload to upload again.

For some reason I also encountered a "quota exceeded" issue which was due to Google having changed query limits to 0 on my project. Creating a new project gave saner query limits.

xemles commented 2 years ago

Oooh! That might solve the issue I'm having, thanks for mentioning that, I didn't know it became obsolete and was confused why I was having invalid requests

bryanseah234 commented 2 years ago

i tried this method, but doesnt work for me :(

schneemaier commented 2 years ago

@zougloub Can you please provide a kind of step by step instruction how to use this modification?

Example "I just copied the code from the browser address bar," - What code, what url etc.

Thanks

m4p commented 2 years ago

I might be doing something wrong, but for me this works, but does not refresh the oauth token. So you need to renew the token manually every hour or so, which kind of makes headless operation impossible.

feacluster commented 2 years ago

If I understand correctly, the OOB will stop working October 2022. I tried the suggestion of putting my own flow.redirect_uri but when I try and authenticate on google, it says, "Error 400: redirect_uri_mismatch". I also tried editing the .client_secrets.json file to use the same flow.redirect_uri instead of http://localhost . But it still gives the same Error 400. Anyone had some luck with this? My gut feel is that the youtube uploader scripts needs to be re-written to fix this?

janisozaur commented 1 year ago

For now this worked for me, but come October it might no longer be valid.

According to https://developers.google.com/identity/protocols/oauth2/resources/oob-migration#desktop-client the URI should be either https://localhost or https://127.0.0.1:

diff --git a/youtube_upload/auth/__init__.py b/youtube_upload/auth/__init__.py
index da7e7a9..4d4277c 100644
--- a/youtube_upload/auth/__init__.py
+++ b/youtube_upload/auth/__init__.py
@@ -14,7 +14,7 @@ YOUTUBE_UPLOAD_SCOPE = ["https://www.googleapis.com/auth/youtube.upload", "https

 def _get_credentials_interactively(flow, storage, get_code_callback):
     """Return the credentials asking the user."""
-    flow.redirect_uri = oauth2client.client.OOB_CALLBACK_URN
+    flow.redirect_uri = "https://localhost"
     authorize_url = flow.step1_get_authorize_url()
     code = get_code_callback(authorize_url)
     if code:

That let me correctly log in and authorize application (after having created a new project in google APIs console due to aforementioned quota reset issue), that redirected me to https://localhost/?code=<base64>&scope=https://www.googleapis.com/auth/youtube.upload%20https://www.googleapis.com/auth/youtube. Copying the <base64> from URL back to youtube-upload prompt allowed me to correctly upload.

feacluster commented 1 year ago

Think I figured it out ( although not 100% sure this is kosher with Google ):

When creating your OAuth credential, I selected "Web application" and put in "https://mysite.com/" for the authorized redirect_uri . Next I went to init.py and put in the same site for "flow.redirect_uri". Last, I deleted the .youtube-upload-credentials.json and tried to upload a new video. It then asked me to put the link in the browser. After doing so, it took me back to https://mysite.com/, however, in the URL I could see the code. I copied this code and pasted it back into youtube-upload script and it worked..

Maybe this method is still deprecated/unsupported. Hopefully others can try and report back!

feacluster commented 1 year ago

Got another dreaded email reminding about the "Action required: Migrate your impacted Oauth out-of-band blah blah blah". In the email I clicked on the "unhappy" face and sent them feedback that this is way over the top. They needs to make things simple and easy to understand. Instead they think everyone who use their tool is some large corporation with a huge IT department..

m4p commented 1 year ago

As inspiration for alternatives to the oob flow, https://github.com/porjo/youtubeuploader might be useful

JThundley commented 1 year ago

I decided to wait until the deadline to see what happened as I figured I wouldn't be able to reliably test the fix. My videos have continued to upload without issue. I uploaded 11 videos on the 7th without touching anything.

On Wed, Aug 31, 2022 at 8:11 AM Martin Pittenauer @.***> wrote:

As inspiration for alternatives to the oob flow, https://github.com/porjo/youtubeuploader might be useful

— Reply to this email directly, view it on GitHub https://github.com/tokland/youtube-upload/issues/349#issuecomment-1233068742, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACH5IV4ZWAAHSRUMWUBPC7TV35YZ3ANCNFSM5TMP36AQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>

Micheal-K commented 1 year ago

For now this worked for me, but come October it might no longer be valid.

According to https://developers.google.com/identity/protocols/oauth2/resources/oob-migration#desktop-client the URI should be either https://localhost or https://127.0.0.1:

diff --git a/youtube_upload/auth/__init__.py b/youtube_upload/auth/__init__.py
index da7e7a9..4d4277c 100644
--- a/youtube_upload/auth/__init__.py
+++ b/youtube_upload/auth/__init__.py
@@ -14,7 +14,7 @@ YOUTUBE_UPLOAD_SCOPE = ["https://www.googleapis.com/auth/youtube.upload", "https

 def _get_credentials_interactively(flow, storage, get_code_callback):
     """Return the credentials asking the user."""
-    flow.redirect_uri = oauth2client.client.OOB_CALLBACK_URN
+    flow.redirect_uri = "https://localhost"
     authorize_url = flow.step1_get_authorize_url()
     code = get_code_callback(authorize_url)
     if code:

That let me correctly log in and authorize application (after having created a new project in google APIs console due to aforementioned quota reset issue), that redirected me to https://localhost/?code=<base64>&scope=https://www.googleapis.com/auth/youtube.upload%20https://www.googleapis.com/auth/youtube. Copying the <base64> from URL back to youtube-upload prompt allowed me to correctly upload.

Hello, I just want to know, can it well work now? after no OOB. I am new, if it still works, I will set it up. thank you very much. I need this to know. @janisozaur

christiangenco commented 1 year ago

I can see from this thread that it's just a one-line change to get new channel authentication working again but for the life of me I can't figure out how to make the change and run this code locally.

Because of this I'm switching to youtubeuploader which seems to be actively maintained.

ZainRizvi commented 1 year ago

The one-line change didn't work for me. Instead, I had to write a custom script to generate the YouTube handle, and then I could pass that handle in to the main function's upload_youtube_video method.

To get the handler and save the credentials:

import google_auth_oauthlib.flow
import googleapiclient.discovery
import googleapiclient.errors
import pickle

def _get_youtube_handler(options):
  credentials_file = "credentials.pickle"

  # Check if credentials file exists
  if os.path.exists(credentials_file):
      # Load stored credentials from file
      with open(credentials_file, "rb") as file:
          credentials = pickle.load(file)
  else:

      # Set up OAuth 2.0 credentials
      scopes = [
        "https://www.googleapis.com/auth/youtube.upload",
        "https://www.googleapis.com/auth/youtube"
      ]
      home = os.path.expanduser("~")
      client_secrets = options.client_secrets or os.path.join(home, ".client_secrets.json")
      flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(
        client_secrets, scopes)
      credentials = flow.run_local_server(port=8890)

      # Save the credentials for future use
      with open(credentials_file, "wb") as file:
          pickle.dump(credentials, file)

  # Create the YouTube Data API client
  youtube = googleapiclient.discovery.build("youtube", "v3", credentials=credentials)

  return youtube

Then I was able to use that handler directly:

from youtube_upload.main import upload_youtube_video

youtube = _get_youtube_handler(options)
video_id = upload_youtube_video(youtube, options, video_path, num_videos, index_num)