-
Notifications
You must be signed in to change notification settings - Fork 128
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
unable to login with api, no returns #128
Comments
Hello, I experience the same troubles since few days. Was working fine before.
From my understanding, it seems that the API cannot get any answer from the server with the API login function (or maybe bad formatted response? ). No change on my side with code that was working well before. |
I think they've changed login procedure, I've just checked the login procedure on the web version, there are some additional fields in the login request. I didn't look closer, but I assume it's some sort of protection. |
My experience lately is that this library is abandoned (which I'm not complaining about), so we're probably on our own in working through this issue. @igorskh mentioned additional fields in the login request. I also see additional fields (although I'm not really sure what was there before): And to me this also looks like additional authentication details to exclude unauthorized clients. Accessing Duolingo via this library has always kind of felt like an unauthorized hack, and now it feels to me like Duolingo might be closing that door. |
That really sucks! I'm having the same issue. |
Yeah, if you look through the calls being made on the login page prior to that call to |
JWT authentication still works. |
Is there a way to acquire a token other than manually extracting one from a browser session, though? |
No easy way that I know of. However, at the moment it's sufficient to get it only once, since they practically don't expire. |
Thanks so much everyone! I'm glad it wasn't just me and that it's sourced from Duolingo. I agree that the API call did seem like low-key hacking, so it doesn't surprise me that they have closed that loophole. I'll just grab the XP progress and other details from my user page for now and submit a request to Duolingo for them to create their own API. |
How do you use this method? |
@KBretz77 you might consider re-opening the issue. Even if you're not hoping for a solution, leaving the issue open serves as a helpful notice for anyone trying to use the library who runs into this problem. :) |
That's a good point, thanks @JASchilz |
@flyinggoatman You can grab your JWT by logging in on duolingo.com and then running this JavaScript, which will output the token into the console: |
The solution by @marvinscham worked for me. Since jwt=None by default - I don't see why L100 is there. |
Has he committed the solution yet? |
For me still does not work. I get "Login failed". |
They’ve probably patched it again... Let me check my code.
From: Antonio ***@***.***>
Sent: 23 May 2023 16:43
To: ***@***.***>
Cc: ***@***.***>; ***@***.***>
Subject: Re: [KartikTalwar/Duolingo] unable to login with api, no returns (Issue #128)
@flyinggoatman<https://github.com/flyinggoatman> I fixed this for my usecase by removing self.jwt = None at https://github.com/KartikTalwar/Duolingo/blob/master/duolingo.py#L100, which then allowed me to instantiate like lingo = duolingo.Duolingo(username='myUsername', jwt='myJWT')
You can grab your JWT by logging in on duolingo.com and then running this JavaScript, which will output the token into the console: document.cookie.match(new RegExp('(^| )jwt_token=([^;]+)'))[0].slice(11);
For me still does not work. I got "Login failed".
—
Reply to this email directly, view it on GitHub<#128 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AAZ2VUS2Q2IL244H4YSEJ6TXHTLLRANCNFSM6AAAAAAVAWDJ5E>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
I used this code to modify the Duolingo API to make JWT authorization work. It's still working for me to this day.
|
@flyinggoatman did you have the time to check if that is still working for you? |
tested today and with the changes
and use jwt token worked. here my main.py for the AWS Lambda function (username,pw and jwt token are Environment Variables of Lambda) def item_already_equipped(lingo, item):
if item == 'streak_freeze':
return lingo.__dict__['user_data'].__dict__['tracking_properties']['num_item_streak_freeze'] > 0
if item == 'rupee_wager':
return lingo.__dict__['user_data'].__dict__['tracking_properties']['has_item_rupee_wager']
def main(a, b):
import duolingo, os
username = os.environ['usernames']
password = os.environ['passwords']
jwt = os.environ['jwt']
print("Test__Tilo__Here")
print("environment variable: " + os.environ['usernames'])
print("loaded jwt (first 10 char: " + jwt[:10])
print("loaded one: " + username)
try:
#lingo = duolingo.Duolingo(username, password)
lingo = duolingo.Duolingo(username=os.environ['usernames'], jwt=os.environ['jwt'])
except ValueError:
raise Exception("Username or login Invalid")
#here the test/report stuff
print("---InfoPart---Start---")
Mylanguages = lingo.get_languages()
print(username + " get_languages for " + str(Mylanguages))
streak_info = lingo.get_streak_info()
print(username +" get_streak_info for " + str(streak_info))
MyInfo = lingo.get_user_info()
print(username +" Info ID: " + str(MyInfo["id"]))
print(username +" Info fullname: " + str(MyInfo["fullname"]))
print(username +" Info location: " + str(MyInfo["location"]))
print(username +" Info contribution_points: " + str(MyInfo["contribution_points"]))
print(username +" Info created: " + str.strip(MyInfo["created"]))
print(username +" Info learning_language_string: " + str(MyInfo["learning_language_string"]))
print(username +" streak_freeze: " + str(lingo.__dict__['user_data'].__dict__['tracking_properties']['num_item_streak_freeze']))
print(username +" rupee_wager: " + str(lingo.__dict__['user_data'].__dict__['tracking_properties']['has_item_rupee_wager']))
user_data_resp = lingo.get_data_by_user_id()
print(username +" Info lingots: " + str(user_data_resp['lingots']))
print(username +" Info totalXp: " + str(user_data_resp['totalXp']))
print(username +" Info monthlyXp: " + str(user_data_resp['monthlyXp']))
print(username +" Info weeklyXp: " + str(user_data_resp['weeklyXp']))
print(username +" Info gems: " + str(user_data_resp['gems']))
print(username +" Info currentCourse.crowns: " + str(user_data_resp['currentCourse']['crowns']))
print("---InfoPart---End---")
#new buy stuff 2020-08-31
stuff_to_purchase = ['streak_freeze', 'rupee_wager']
for item in stuff_to_purchase:
if(item_already_equipped(lingo, item)):
print("Item "+ item + " already equipped! Skipping...")
continue
try:
print("Trying to Buy " + item + " for " + username)
lingo.buy_item(item, 'es')
print("Bought " + item + " for " + username)
except duolingo.AlreadyHaveStoreItemException: # no longer triggered AFAIK
print("Item Already Equipped")
except Exception:
raise ValueError("Unable to buy " + item) cheers. |
Hello everyone, Like you, I was quite disheartened when the Duolingo API library stopped working and was giving an authorization error. By examining how Duolingo operates through the browser console, I managed to create a minor fix, and now everything is running smoothly on my end. I have uploaded a version with the fix in this repository: https://github.com/tier61wro/Duolingo. Perhaps some of you will find this useful! I'm not confident that my fix will work forever, so I don't think it makes sense to make a merge request into the main repository at this point. Best regards, |
I've found that there is still an unauthenticated endpoint that allows you to retrieve user data. Perhaps there are more methods that can be called on this endpoint, but I am only interested in some public user data. |
Fuck that's dangurous. My email is just... there... |
I played around with it and it seems like the endpoint returns different data for your own username depending on whether you are logged in or not. They use cookies to authenticate the API request. So your email and phone number are not really exposed, even though it looks like it. |
@tier61wro Thanks for sharing it, but unfortunately your fix doesn't work for me: Traceback (most recent call last):
File "/Users/matt/Projects/duolingo/test.py", line 3, in <module>
lingo = duolingo.Duolingo('username', 'password')
File "/Users/matt/Projects/duolingo/duolingo.py", line 66, in __init__
self._login()
File "/Users/matt/Projects/duolingo/duolingo.py", line 108, in _login
self.jwt = request.headers['jwt']
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/requests/structures.py", line 52, in __getitem__
return self._store[key.lower()][1]
KeyError: 'jwt' I was able to use a combination of @Vag-Soft's patch #128 (comment) with @flyinggoatman's instantiation #128 (comment) though, which is good enough for my personal use. |
To make this super straightforward, here's the full fix based on @mbrookes's recommendation, which worked for me (thank you!):
|
Hi! Nice work with this fix! I managed to download and started the UI setup. By running the code Any ideas? |
I will answer to myself. The "username" in the login is not the login email address but the user profile -> user name just above "joined September 2022" etc. info in the Duolingo web site. Now working! |
Ever since February 16th, I've been unable to access the API, even after verifying my username/password. I keep getting this exception:
Traceback (most recent call last):
File "[USER SCRIPT] ", line 10, in
lingo = duolingo.Duolingo('[USER], [PW]')
File "[USER ENV] \lib\site-packages\duolingo.py", line 66, in init
self._login()
File "[USER ENV] \lib\site-packages\duolingo.py", line 105, in _login
attempt = request.json()
File "[USER ENV] \lib\site-packages\requests\models.py", line 975, in json
raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
The text was updated successfully, but these errors were encountered: