Skip to content
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

✨ Support Authentication #11

Open
Neppu-Nep opened this issue Feb 28, 2022 · 14 comments
Open

✨ Support Authentication #11

Neppu-Nep opened this issue Feb 28, 2022 · 14 comments
Labels
enhancement New feature or request

Comments

@Neppu-Nep
Copy link

Not sure if you already knew about it or not but from my testing you can do authenticated requests by using cookies. (Not sure how long will this last before needing to repeat the process again).

Steps to do

  1. Open incognito browser and open developer console.
  2. Browse to network tab and enable Preserve log.
  3. Type in set_registration in the network search bar.
  4. Go to https://www.youtube.com/ and login as usual.
  5. Then select the 2nd result and then copy the whole cookie from the request headers.
  6. The cookie values needed are SID, HSID, SSID, APISID and SAPISID. You can delete the rest values or just leave them.
  7. Generate SAPISIDHASH by inserting SAPISID value obatained from above into the function below.
import time
import hashlib

def hashString(password):
    hash_object = hashlib.sha1(password.encode())
    pbHash = hash_object.hexdigest()
    return pbHash

current_time = str(int(time.time()))
origin = "https://www.youtube.com"
sapisidhash = hashString(f"{current_time} {sapisid} {origin}")
  1. Pass the headers below when making requests
headers = {
    "Authorization": f"SAPISIDHASH {current_time}_{sapisidhash}",
    "Cookie": cookie_string_from_step_6,
    "x-origin": origin
}
  1. Your requests are now authenticated requests.

Notes

Reason why incognito is required is because for some reason the SID, HSID and SSID cookies aren't included in the request headers and instead it relies on x-goog-authuser header value if you are already logged in. Clearing cache doesn't seem to include it either.

I'm not really good at actually implementing stuffs so would be grateful if you could add the feature into the existing code.

@tombulled
Copy link
Owner

Hi @Loli-Killer, thanks for raising this issue! I was aware that it was possible to make authenticated requests using cookies in this way, however as it requires such a manual action by the user, I haven't included the functionality in the codebase.

I'd really love to get OAuth working in some way, and I believe the community has been able to make some headway on this, so it's something I've been meaning to look into further. I'll keep this issue open, and hopefully will get a chance to explore the issue of authentication more soon 🙂

@BRUHItsABunny
Copy link

BRUHItsABunny commented Apr 15, 2022

Getting oauth to work is relatively easy

If you can read Golang this might help you out:
https://github.com/BRUHItsABunny/go-android-firebase/blob/326f8ce0c3f2b62f6199078268b29456535023ce/api/api.go#L128
My personal (private) innertube library uses that function to fetch the auth token then used as Bearer authorization value.
You would have to figure out what the "data" (url.Values object) would be but other than that pretty straightforward.
This was reverse engineered from the Android YouTube app btw

@tombulled
Copy link
Owner

@BRUHItsABunny Awesome! Thanks for providing that link, your implementation looks incredibly helpful.

I've also found the following resource which looks like it might come in handy:

I'll see if I can get some sort of a POC script for OAuth working using the resources provided in this issue

@tombulled
Copy link
Owner

tombulled commented Apr 15, 2022

Here's a quick POC script I've whipped together using 89z/mech which requests an Oauth2 token for YouTube TV:

import httpx
import pprint

client = httpx.Client()

CLIENT_ID = "861556708454-d6dlm3lh05idd8npek18k6be8ba3oc68.apps.googleusercontent.com"
CLIENT_SECRET = "SboVhoG9s0rNafixCSGGKXAT"

device_data = client.post(
    "https://oauth2.googleapis.com/device/code",
    data=dict(
        client_id=CLIENT_ID,
        scope="https://www.googleapis.com/auth/youtube",
    ),
).json()

device_code = device_data["device_code"]

print('== YouTube TV OAuth ==')
print("  1. Visit:", device_data["verification_url"])
print("  2. Enter code:", device_data["user_code"])
print()
input("Once done, press enter to request a token...")

token_data = client.post(
    "https://oauth2.googleapis.com/token",
    data=dict(
        client_id=CLIENT_ID,
        client_secret=CLIENT_SECRET,
        device_code=device_code,
        grant_type="urn:ietf:params:oauth:grant-type:device_code",
    ),
).json()

pprint.pprint(token_data)

I'll keep fiddling and will see if I can get any further

@BRUHItsABunny
Copy link

BRUHItsABunny commented Apr 15, 2022

Oh yea I remember seeing that a while ago as well.
I personally opted out of TV oauth due to it requiring manual input upon retrieval, instead I opted into relying on the Google master token however that comes with it's own set of drawbacks. (A compromised master token has access to everything, eg: Drive, Gmail, any apps you may have linked to the Google account)

For that reason I use a dedicated Google account for the innertube automation I do but other than that it was worth it to me given auth tokens are only valid for a couple hours at a time.

@tombulled tombulled added the enhancement New feature or request label Dec 1, 2022
@tombulled tombulled changed the title Authentication questions ✨ Support Authentication Dec 1, 2022
@tombulled
Copy link
Owner

Just stumbled upon YouTube.js. It looks like they have a pretty concrete implementation of the YouTube TV OAuth flow - https://github.com/LuanRT/YouTube.js/blob/main/src/core/OAuth.ts

@tombulled
Copy link
Owner

@BRUHItsABunny
Copy link

BRUHItsABunny commented Dec 29, 2022

Those last links are similar to my implementation as well, long lived master token oauth

mine
I didn't implement a way to get master tokens yet but i think this looks like that missing piece

@0dminnimda
Copy link

What is the status of this?

@tombulled
Copy link
Owner

What is the status of this?

No further updates to report on this unfortunately, beyond the investigations in this issue. At some point I plan to implement the YouTube TV OAuth flow into innertube, but finding the time is unfortunately proving challenging these days

@ghost
Copy link

ghost commented Sep 18, 2023

If you can read Golang this might help you out: https://github.com/BRUHItsABunny/go-android-firebase/blob/326f8ce0c3f2b62f6199078268b29456535023ce/api/api.go#L128

not sure how this helps. this assumes you already have the masterToken, which is quite difficult to get. I mean this from a programmatic standpoint, which manually copying cookies from a browser is not.

I've also found the following resource which looks like it might come in handy:

I am the author of that code, the current implementation is here:

https://github.com/1268/media/blob/v1.6.4/youtube/token.go

A couple of potentially handy links for this:

FYI this code is based on the Google Services Framework 4.4, which is at least ten years old at this point. since version 5, URL like this is used instead:

https://accounts.google.com/embedded/setup/android

@tombulled
Copy link
Owner

My current stance on authentication is that I'd prefer to avoid using a master token and am not a big fan of relying on browser cookies. OAuth is the preferred approach, and so the YouTube TV OAuth flow is looking like the best way forward, at least for now

@ghost
Copy link

ghost commented Sep 20, 2023

LOL WTF I just found another one for YouTube TV ([email protected]):

> curl -X POST 'https://oauth2.googleapis.com/device/code?client_id=627431331381.apps.googleusercontent.com&scope=https://www.googleapis.com/auth/youtube'
{
  "device_code": "AH-1Ng04yWzgknyxf0Zx1TKVJRplVL1KfgASq5xzWx9g-FQJUC00HuF8ZtuU2dNMCMRbSes3keVYRoBmPdMC3OBcRCHcm6yTYQ",
  "user_code": "JSR-LBX-RJB",
  "expires_in": 1800,
  "interval": 5,
  "verification_url": "https://www.google.com/device"
}

and:

client_secret O_HOjELPNFcHO_n_866hamcO

@hussamh10
Copy link

@Loli-Killer Thanks for the step by step guide on how to create the headers for authentication
However, I am confused on where do I pass the headers (and how) when making requests?
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants