captn3m0 / forteller-dl

Downloads MP3 files from Foreteller Games, without using the app. You must purchase the media first from https://www.fortellergames.com/.
MIT License
3 stars 3 forks source link

Authentication issue #1

Open Ziver opened 2 years ago

Ziver commented 2 years ago

Hi, I've been trying to use the script do download audio files but I'm having issues with the authentication. The script retrieves the Refresh Token, Access Token correctly and also the free chapters but when it tries to download the payed files(I have bought the Jaws audio and can access them through the app) I get a error message:

failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request

A second less sever issues I also have noticed is that the script does not correctly see existing files, it always re-downloads already existing files, I had to change the line like below to get this fixed (not that familiar with PHP so not sure why this is not working correctly): if (!file_exists($filename)) { to: if (file_exists($filename) == false) {

captn3m0 commented 2 years ago

Haven't tested this in a while, will check on this when I get some time.

captn3m0 commented 2 years ago

Tested this locally once - worked perfectly fine. Here was my output:

php run.php ceph_jaws
Jaws of the Lion/Prologue - Prologue.mp3
Jaws of the Lion/1 Roadside Ambush - Introduction.mp3
Jaws of the Lion/1 Roadside Ambush - Conclusion.mp3
Jaws of the Lion/2 A Hole in the Wall - Introduction.mp3
Jaws of the Lion/2 A Hole in the Wall - Conclusion.mp3
Jaws of the Lion/3 The Black Ship - Introduction.mp3
Jaws of the Lion/3 The Black Ship - Trigger 1.mp3
Jaws of the Lion/3 The Black Ship - Trigger 2.mp3
Jaws of the Lion/3 The Black Ship - Conclusion.mp3
Jaws of the Lion/4 A Ritual in Stone - Introduction.mp3
Jaws of the Lion/4 A Ritual in Stone - Trigger.mp3
Jaws of the Lion/4 A Ritual in Stone - Conclusion.mp3
Jaws of the Lion/5 A Deeper Understanding - Introduction.mp3
Jaws of the Lion/5 A Deeper Understanding - Trigger.mp3
Jaws of the Lion/5 A Deeper Understanding - Conclusion.mp3
Jaws of the Lion/6 Corrupted Research - Introduction.mp3
Jaws of the Lion/6 Corrupted Research - Conclusion.mp3
Jaws of the Lion/7 Sunken Tumor - Introduction.mp3
Jaws of the Lion/7 Sunken Tumor - Trigger.mp3
Jaws of the Lion/7 Sunken Tumor - Conclusion.mp3
Jaws of the Lion/8 Hidden Tumor - Introduction.mp3

I ran it again, and the existing files were correctly detected and skipped as well. What system are you running this on? Can you give the output for php --version as well please?

Please double check the values in config.php. Here's how mine looks:


<?php

const EMAIL = 'email@example.com';
const PASSWORD = 'passwordgoeshere';
Ziver commented 2 years ago

Hmm, my PHP version should be pretty old "PHP 5.5.9", I do not have access to a newer version right now, will try to setup a VM with a newer version and test.

I have tried to change the config file and when I purposefully add incorrect values I do not get any refresh and access token so I assume that my details are correct.

I changed some code to be able to get the error message from the request function:

400: {"message":"Unable to find user profile"}

This looks very strange, do you know if there are eu servers that I should connect to instead of the us one?

captn3m0 commented 2 years ago

Can't really support such an old PHP version, sorry. Let me know if it still breaks on a supported PHP release.

Ziver commented 2 years ago

That is fully understandable, but sorry to say running in a VM with "PHP 8.0.8" I get the same error.

One question about the config.php file, I assumed I was supposed to put the Forteller account information, is this correct?

captn3m0 commented 2 years ago

Yes, that's correct.

I'm wondering if it's an account age issue? Maybe they go via different auth.

Could you confirm how you are invoking the script? OS/Command at least. And would you be okay sending me your temporary creds by any chance? (Email in bio)

Ziver commented 2 years ago

It could be account age as it was created a month ago.

I just execute the script as you described: php ./run.php ceph_jaws

I'm a bit hesitant to give out credentials, but I'm happy to run any test/debugging you would need.

captn3m0 commented 2 years ago

What's the VM you're running this on?

Planning to create a Docker image for this, will that work for you?

Ziver commented 2 years ago

It is just a standard Ubuntu VM where I installed php8-cli, a container should work for me.

captn3m0 commented 2 years ago

I created a docker image and published it on GitHub Packages. Could you try this (you will need to create a .env file)

docker run -it --init --volume "$HOME/Downloads:/downloads" --env-file .env ghcr.io/captn3m0/forteller-dl:main ceph_jaws /downloads

Ziver commented 2 years ago

Seems there is something wrong with the Image name as I got:

Unable to find image 'ghcr.io/captn3m0/forteller-dl:main' locally
docker: Error response from daemon: Get https://ghcr.io/v2/captn3m0/forteller-dl/manifests/main: unauthorized.
See 'docker run --help'.

I built the container manually from the repo and ran with the command you provided but get the same message:

> docker run -it --init --volume "downloads:/downloads" --env-file config.env 8876d9cc75a5 ceph_jaws /downloads
Saving files in /downloads
/downloads/Jaws of the Lion/Prologue - Prologue.mp3
/downloads/Jaws of the Lion/1 Roadside Ambush - Introduction.mp3
/downloads/Jaws of the Lion/1 Roadside Ambush - Conclusion.mp3
/downloads/Jaws of the Lion/2 A Hole in the Wall - Introduction.mp3

Warning: file_get_contents(https://us-central1-forteller-platform.cloudfunctions.net/audio/zOoRCBJBRD47XjQAmAkS/YXyAjN87G6fJ6BiFVwv3/cMDrAuQ8s1io1MKRCbSI): Failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request
 in /src/run.php on line 88
Failed to download https://us-central1-forteller-platform.cloudfunctions.net/audio/zOoRCBJBRD47XjQAmAkS/YXyAjN87G6fJ6BiFVwv3/cMDrAuQ8s1io1MKRCbSI

I made some changes to the php file to better see the error message from the server in the request function, if it is ok I will create a pull request for it.

captn3m0 commented 2 years ago

Somehow I missed the "user profile" error. It's possible that you face this because of a token that expired quickly. Can you check at which file do you get this error (The first pay-walled file or after a few have been downloaded?)

If it's just a token issue, re-running the script ought to fix the issue - you might have to delete a few corrupt files. Will update the script to take token refresh into account if I can confirm this as the issue.

Ziver commented 2 years ago

It is always at the first pay-wall item, It is always possible to download the free tracks (tried through the REST api without credentials.

Like you said it must be something different with newer accounts. I tried decompiling the official app but could not find any obvious place where this authentication was happening.

captn3m0 commented 2 years ago

You have a login via email+password rather than any of the social methods, right?

The last time I reversed the app, it delegated auth to Firebase entirely.

Ziver commented 2 years ago

Yes that is correct, I use a separate email and password for Forteller, it is not same as my Google account.

Ziver commented 2 years ago

I managed to log DNS queries, looks like Forteller has migrated to Azure instead of Google Cloud (or they use multiple cloud vendors). The OAuth seems to still be done through Google though.

DNS Queries to (In order):

captn3m0 commented 2 years ago

That's weird, I'm running the script, and it fetches the files straight from cloudfunctions.net:

curl --request GET \
  --url https://us-central1-forteller-platform.cloudfunctions.net/audio/zOoRCBJBRD47XjQAmAkS/YXyAjN87G6fJ6BiFVwv3/cMDrAuQ8s1io1MKRCbSI \
  --header 'Authorization: Bearer JWTTOKEN'

Maybe it's a new app update. Are you trying the iOS or Android app?

captn3m0 commented 2 years ago

Damn it, they've thrown it behind Azure DRM. So glad I got my download before this change.

Ziver commented 2 years ago

That is unfortunate news, I guess that is it then. With DRM it should be very difficult the get the files without any clear vulnerability.

captn3m0 commented 2 years ago

Nah, it seems to be standard AES-128 Azure DRM (not Fairplay or Widevine). My assumption was that streamlink should be able to decode it, but doesn't look like that's the case.

Have some WIP, but it's all useless unless I can get the decryption to work - will just write a streamlink plugin perhaps.

captn3m0 commented 1 year ago

Got around to working on this today. Wrote up a yt-dlp plugin, since that seemed like the easiest way. The code, with instructions on how to use it is here: https://github.com/captn3m0/yt-dlp/pull/1

Will keep this issue open for feedback, but plan to just upstream the plugin to the official yt-dlp project, so it should work easily everywhere.