omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Authorization with OAuth

    Pythonista
    youtube oauth
    3
    13
    10083
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Obl
      Obl last edited by

      I wrote a little script that gets me a video-Id from Youtube that I want to add to a playlist. Now I tried to execute the following:

      #add to playlist
      url_post='https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&key='+key
      data={"snippet": {
          "playlistId": playListId,
          "resourceId": {
              "videoId": videoId,
              "kind": "youtube#video"
              }
          }
      }
      data_json=json.dumps(data)
      response=requests.post(url_post, data=data_json)
      

      I got a 401-Unauthorized and read the following link https://developers.google.com/youtube/v3/docs/playlistItems/insert where is mentioned, that I have to authenticate with OAuth. So I created some OAuth 2.0-Client-IDs in https://console.developers.google.com.
      But now I don't have any clue how to use OAuth to get this working in Pythonista.
      So how can I authenticate at Youtube to add a Video to my playlist?

      1 Reply Last reply Reply Quote 0
      • mikael
        mikael last edited by

        It is not exactly trivial. Below is the code I have used to get into Google Calendar.

        #coding: utf-8
        import json, requests, time
        import requests
        from oauth2client import _helpers, _pure_python_crypt
        
        '''
        Prerequisites:
        
        * Downloaded a JSON private key file from Google
        * Have your service account email address, probably something ending in iam.gserviceaccount.com
        * Know what the ”scope” is - e.g. for retrieving your calendar this is 'https://www.googleapis.com/auth/calendar.readonly'
        * Have installed oauth2client
        '''
        
        with open(json_file_name, 'r') as file_obj:
          client_credentials = json.load(file_obj)
        private_key_pkcs8_pem = client_credentials['private_key']
        signer = _pure_python_crypt.RsaSigner.from_string(private_key_pkcs8_pem)
        
        header = {'typ': 'JWT', 'alg': 'RS256'}
        now = int(time.time())
        payload = {
                'aud': 'https://www.googleapis.com/oauth2/v4/token',
                'scope': scope,
                'iat': now,
                'exp': now + 3600, # 1 hour in seconds
                'iss': service_account_email_address
        }
        segments = [
                _helpers._urlsafe_b64encode(_helpers._json_encode(header)),
                _helpers._urlsafe_b64encode(_helpers._json_encode(payload)),
        ]
        signing_input = b'.'.join(segments)
        signature = signer.sign(signing_input)
        segments.append(_helpers._urlsafe_b64encode(signature))
        claim = b'.'.join(segments)
        
        post_data = {
                'grant_type':'urn:ietf:params:oauth:grant-type:jwt-bearer',
                'assertion':claim
        }
        req = requests.post('https://www.googleapis.com/oauth2/v4/token', post_data)
        resp = req.json()
        access_token = resp['access_token']
        auth_header = {
                'Authorization':'Bearer ' + access_token
        }
        
        # Use the header in service requests, e.g.
        req = requests.get(request_url, headers = auth_header)
        
        1 Reply Last reply Reply Quote 1
        • Obl
          Obl last edited by

          Finally I found some time to try your approach and voila! it starts to work! Now I am able to connect to the server and get the tokens, everything works until I want to add the video to the playlist. Then I get a

          forbidden (403)	playlistItemsNotAccessible
          

          I will post my (modified) code here once again:

          def playlistItem_insert(videoId, key):
          with open(CLIENT_SECRETS_FILE, 'r') as file_obj:
             client_credentials = json.load(file_obj)
          private_key_pkcs8_pem = client_credentials['private_key']
          signer = _pure_python_crypt.RsaSigner.from_string(private_key_pkcs8_pem)
          
          header = {'typ': 'JWT', 'alg': 'RS256'}
          now = int(time.time())
          payload = {
                 'aud': 'https://www.googleapis.com/oauth2/v4/token',
                 'scope': 'https://www.googleapis.com/auth/youtube.force-ssl',
                 'iat': now,
                 'exp': now + 3600, # 1 hour in seconds
                 'iss': service_account_email_address
          }
          segments = [
                 _helpers._urlsafe_b64encode(_helpers._json_encode(header)),
                 _helpers._urlsafe_b64encode(_helpers._json_encode(payload)),
          ]
          signing_input = b'.'.join(segments)
          signature = signer.sign(signing_input)
          segments.append(_helpers._urlsafe_b64encode(signature))
          claim = b'.'.join(segments)
          
          post_data = {
                 'grant_type':'urn:ietf:params:oauth:grant-type:jwt-bearer',
                 'assertion':claim
          }
          req = requests.post('https://www.googleapis.com/oauth2/v4/token', post_data)
          resp = req.json()
          access_token = resp['access_token']
          auth_header = {
                 'Authorization':'Bearer ' + access_token
          }
          
          # Use the header in service requests, e.g.
          d={'snippet': { 
          'playlistId': PLAYLIST_ID, 'resourceId': { 
          'kind': 'youtube#video', 
          'videoId': videoId}
          }
          }
          req = requests.post('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&key='+key, json=d, headers = auth_header)
          req.raise_for_status()
          return req.status_code
          

          Parameters are all available. The problem occurs in line req = requests.post(...)
          Maybe someone has better eyes than me...

          mikael 1 Reply Last reply Reply Quote 0
          • mikael
            mikael @Obl last edited by

            @Obl, looking at the list of scopes, I would guess that you need to use the https://www.googleapis.com/auth/youtube.upload scope.

            1 Reply Last reply Reply Quote 0
            • Obl
              Obl last edited by

              I tried your approach, but with the same result: forbidden (403) playlistItemsNotAccessible.

              I found the scope in this site: https://developers.google.com/youtube/v3/docs/playlistItems/insert
              There is also some Python Code, but it's also not working in Pythonista.

              1 Reply Last reply Reply Quote 0
              • JonB
                JonB last edited by JonB

                are you specifying a playlist Id that you own? According to the docs, and to stack overflow, you can only add to your own playlist, not someone else's.

                You should be able to try your request fields using the form below, to see if your entry is valid...

                https://developers.google.com/youtube/v3/docs/playlistItems/insert

                1 Reply Last reply Reply Quote 0
                • Obl
                  Obl last edited by

                  Yes, it is my own playlist. On the Google site it is possible to add a video to the playlist. But the site is not the same as the code used.

                  1 Reply Last reply Reply Quote 0
                  • JonB
                    JonB last edited by

                    You should use the form on the API page. How are you getting the platlistid? Maybe you should use the API that gets a list of playlists, that way you know it is valid...

                    1 Reply Last reply Reply Quote 0
                    • Obl
                      Obl last edited by

                      I know the playlistId and also the videoId. The are definitive correct and not the problem.

                      1 Reply Last reply Reply Quote 0
                      • JonB
                        JonB last edited by

                        Authorization

                        This request requires authorization with at least one of the following scopes (read more about authentication and authorization).

                        Scope
                        https://www.googleapis.com/auth/youtubepartner
                        https://www.googleapis.com/auth/youtube
                        https://www.googleapis.com/auth/youtube.force-ssl

                        1 Reply Last reply Reply Quote 0
                        • Obl
                          Obl last edited by

                          As you can see in my already posted Code, I already use one of the right scopes. I also tried the other two scopes, still Errorcode 403. I also checked the other URLs in Google OAuth Playground, they are also correct.

                          mikael 1 Reply Last reply Reply Quote 0
                          • mikael
                            mikael @Obl last edited by

                            @Obl, have you found any samples that would do the same thing, in any other programming language?

                            1 Reply Last reply Reply Quote 0
                            • JonB
                              JonB last edited by JonB

                              Stupid question, but does your service account automatically have access to your youtube account? It is not obvious to me that it would.

                              I think you may be better off getting credentials via a regular oauth flow, which is what the api explorer does.

                              Here i have implementd a modified version of the web quickstart from the youtube python api examples, which presents a webview that authorizes to a flask webserver. Then saves the access token to creds.json.

                              This requires you to add http://localhost:8090/oauth2callback to the allowed callback uris in the developer console.

                              Also, a bunch of packages need to get installed via stash pip --
                              google-api-python-client
                              google-auth
                              google-auth-oauthlib
                              google-auth-httplib2

                              Once you have the token for your user, you can use the google youtube python api. I started with the youtube/api-samples repo on github, replaced their get_authenticated_service with one that uses the saved creds.json.

                              # Authorize the request and store authorization credentials.
                              def get_authenticated_service():
                                from oauth2client.client import AccessTokenCredentials
                                creds=json.load(open('creds.json'))
                                credentials= AccessTokenCredentials(access_token=creds['token'],user_agent='JonTestApp')
                                return build(API_SERVICE_NAME, API_VERSION, credentials = credentials)
                              

                              After that, I was able to create a playlist.

                              1 Reply Last reply Reply Quote 0
                              • First post
                                Last post
                              Powered by NodeBB Forums | Contributors