diff --git a/assets/js/player.js b/assets/js/player.js index ecdc04485..7c3481094 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -434,7 +434,7 @@ if (!video_data.params.listen && video_data.params.quality === 'dash') { } player.vttThumbnails({ - src: '/api/v1/storyboards/' + video_data.id + '?height=90', + src: '/api/v1/storyboards/' + video_data.id + '?height=90' + `${video_data.invidious_companion_check_id ? `&check=${video_data.invidious_companion_check_id}` : ""}`, showTimestamp: true }); diff --git a/config/config.example.yml b/config/config.example.yml index 7cc480c64..c058c56c2 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -89,6 +89,16 @@ db: ## #invidious_companion_key: "CHANGE_ME!!" +## +## API key for Invidious companion, used for securing the communication +## between Invidious and Invidious companion. +## The key needs to be exactly 16 characters long. +## +## Accepted values: true, false +## Default: true +## +#invidious_companion_verify_requests: true + ######################################### # # Server config diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 7853d9a3b..2ee6e89c2 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -173,6 +173,9 @@ class Config # Invidious companion API key property invidious_companion_key : String = "" + # Verify requests on endpoints that use Invidious companion + property invidious_companion_verify_requests : Bool = true + # Saved cookies in "name1=value1; name2=value2..." format @[YAML::Field(converter: Preferences::StringToCookies)] property cookies : HTTP::Cookies = HTTP::Cookies.new diff --git a/src/invidious/helpers/utils.cr b/src/invidious/helpers/utils.cr index 5637e5338..29936010c 100644 --- a/src/invidious/helpers/utils.cr +++ b/src/invidious/helpers/utils.cr @@ -384,9 +384,13 @@ def parse_link_endpoint(endpoint : JSON::Any, text : String, video_id : String) return text end -def encrypt_ecb_without_salt(data, key) +def ecb_without_salt(data, key, encrypt : Bool) cipher = OpenSSL::Cipher.new("aes-128-ecb") - cipher.encrypt + if encrypt + cipher.encrypt + else + cipher.decrypt + end cipher.key = key io = IO::Memory.new @@ -394,11 +398,25 @@ def encrypt_ecb_without_salt(data, key) io.write(cipher.final) io.rewind - return io + if encrypt + return io + else + return io.gets_to_end + end end def invidious_companion_encrypt(data) timestamp = Time.utc.to_unix - encrypted_data = encrypt_ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key) + encrypted_data = ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key, encrypt: true) return Base64.urlsafe_encode(encrypted_data) end + +def invidious_companion_decrypt(check_id) + check_id_decoded = Base64.decode_string(check_id) + begin + decrypted_data = ecb_without_salt(check_id_decoded, CONFIG.invidious_companion_key, encrypt: false) + rescue + return nil + end + return decrypted_data.as(String).split("|") +end diff --git a/src/invidious/routes/api/v1/videos.cr b/src/invidious/routes/api/v1/videos.cr index 6a3eb8ae3..6c191ba2a 100644 --- a/src/invidious/routes/api/v1/videos.cr +++ b/src/invidious/routes/api/v1/videos.cr @@ -181,6 +181,18 @@ module Invidious::Routes::API::V1::Videos id = env.params.url["id"] region = env.params.query["region"]? + if CONFIG.invidious_companion.present? && CONFIG.invidious_companion_verify_requests + invidious_companion_check_id = env.params.query["check"]? + if check_id = invidious_companion_check_id + video_id = invidious_companion_decrypt(check_id).try &.[1] + if id != video_id + haltf env, 401, "ID incorrect." + end + else + haltf env, 401, "No check ID." + end + end + begin video = get_video(id, region: region) rescue ex : NotFoundException diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index 26ba65f74..a740f02e8 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -1,6 +1,3 @@ -<% - invidious_companion_check_id = invidious_companion_encrypt(video.id) if invidious_companion -%>