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

updated app ids #34

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Conversation

fl4shback
Copy link

@fl4shback fl4shback commented Jan 23, 2022

Some parts of the Ubisoft API recently started to reject requests made by the legacy "Ubisoft Club" app IDs.

I changed the IDs to the new ones.

Fixes #33, #37

@wearepariah
Copy link

Can confirm, fixes #33 - thank you!

@yessenbayev
Copy link

yessenbayev commented Jan 26, 2022

This PR needs to merge ASAP, the Ubisoft Connect plugin does not work at all anymore, as of 1/25/2022.

@FriendsOfGalaxy could you prioritize reviewing it?

@TrakoDev
Copy link

just used this connect library today, changed lines to

CLUB_APPID = "314d4fef-e568-454a-ae06-43e3bece12a6"
CLUB_GENOME_ID = "85c31714-0941-4876-a18d-2c7e9dce8d40"

confirmed fix

image

@SparrowBrain
Copy link

Works for me too.

@adrianinsaval
Copy link

Any reason why this isn't getting merged?

@fl4shback
Copy link
Author

@FriendsOfGalaxy seems inactive since last September, maybe they stopped maintaining the plugins..

@francoisaudic
Copy link

Works for me too. Hope someone could fix the problem by merging the fix with the master.

@eduardo-publi
Copy link

Updated GOG Client to 2.0.46 Beta (Feb 16, 2022), but disconnect remains... just updated Ids like this PR, and started working again

@draeath
Copy link

draeath commented Mar 5, 2022

Can we get some attention on this PR, please? We have a known-working fix here. Seems like a quick and safe merge. (assuming maintainer wouldn't want the two commits squashed to one, that is)

@abelcheung
Copy link

Wonder if anybody else in GoG has commit access to this account. It has a email address, so if anybody is willing to ping them with email...

@dCSeven
Copy link

dCSeven commented Mar 18, 2022

I pinged friendsofgalaxy per email, but am not confident, that he responds, since the github user seems inactive for half a year now.

@abelcheung
Copy link

I have tried to file support request in GoG client, but things don't look good so far:

  • Support requests are not avaiable on web login, people are told to access ticket through email
  • No email is sent to me for any confirmation, status or whatsoever (also checked spam folder). But I do receive their advertising email every single day.

Although I'd like to hope for situation improving in future, but please also prepare for the worst too -- we players are on our own now.

@milroneth
Copy link

milroneth commented Mar 23, 2022

I have tried to file support request in GoG client

As it is clearly stated in GOG Galaxy, they are not responsible for 3rd party integrations so they can do nothing about this anyway and we shouldn't bug them about it, we have always been on our own regarding this. The GOG client is already understuffed and hanging by a thread, let's please not waste their limited time with things that are out of their control.

Friends of galaxy is a community project, the bad news is that the maintainer has gone dark for the past months.

@muhasturk
Copy link

is it possible to change integration url that is embedded in GOG Galaxy official client?

@abelcheung
Copy link

@muhasturk Nope, that's why I think official intervention is needed. But, well, check the comment above. Not gonna discuss anymore, situation won't change anyway. GoG had possibly pulled the plug on python integration development as a whole, as the main workhorse developer has quitted or at least no longer working on it. Right now manual modification of ID is the way to go.

@scyto
Copy link

scyto commented Apr 5, 2022

@milroneth @turbo25 @yessenbayev
any chance one of you can approve this PR?
i also confirm it fixed the issue.

@milroneth
Copy link

@milroneth @turbo25 @yessenbayev any chance one of you can approve this PR? i also confirm it fixed the issue.

We already have, and you can too! An approval on GitHub is just the proper way to say "this works as intended and the code looks good, I approve of this, please merge it", instead of commenting without offering anything more. That way the maintainer can easily see that a PR has a certain number of approvals without reading and counting comments, and go ahead and merge it.

None of us has the power to merge, only the (now disappeared) maintainer of the repo.

@scyto
Copy link

scyto commented Apr 6, 2022

@milroneth thanks for explaining reviewers don't get merge rights, never realized that.

Is the disappeared maintainer at the repo or the org (FriendsOfGalaxy) level?

I always thought folks at the org level can take control of any repo in the org?

@yessenbayev
Copy link

In the worst case scenario, if the maintainer is no longer available, we can collaborate with GOG, by cloning the integrations to a new user/organization and asking GOG to pull integrations from that new cloned repo.

@francoisaudic
Copy link

The ID has once again changed

What are the new ID ?

Credit to JustThat70 CLUB_APPID = "f35adcb5-1911-440c-b1c9-48fdc1701c68" CLUB_GENOME_ID = "5b36b900-65d8-47f3-93c8-86bdaa48ab50"

Thank you

@fl4shback
Copy link
Author

Updated the IDs in the PR in case it ever gets merged...

@bradgearon
Copy link

bradgearon commented Oct 11, 2022 via email

Copy link

@KS-HTK KS-HTK left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So they changed the IDs AGAIN.

Looking at them today they seem to be the following.

CLUB_APPID = "314d4fef-e568-454a-ae06-43e3bece12a6"
CLUB_GENOME_ID = "85c31714-0941-4876-a18d-2c7e9dce8d40"

EDIT: It should be possible to retrieve these actively. So this constantly changing may end.
If I find the time I might try implementing that in a few days.
They can be found in one of the get requests to https://ubisoftconnect.com/invalid or any other invalid page at that domain one of the GET requests sent by the 404 page contains them in the request header

https://connect.ubisoft.com/sdk.html?env=PROD&appId=314d4fef-e568-454a-ae06-43e3bece12a6&genomeId=85c31714-0941-4876-a18d-2c7e9dce8d40&thirdPartyfalse=&lang=en-US&nextUrl=https://ubisoftconnect.com/invalid?isSso=true&host=https://ubisoftconnect.com

@drmaxx
Copy link

drmaxx commented Oct 21, 2022

Here is a one-liner to quickly check/get the IDs:

# short version
curl -s https://ubisoftconnect.com/invalid | grep -Eo 'APP_ID.{0,40}|GENOME_ID.{0,40}'
# long version, readable parameter
curl --silent https://ubisoftconnect.com/invalid | grep --extended-regexp --only-matching 'APP_ID.{0,40}|GENOME_ID.{0,40}'

I'm sure this can be enhanced, but for me it helps. 😄

Let's hope GOG sorts out the Plugin updates / repo access fuu soonish. Has been a year now since the last update in this repo. 😞

@wearepariah
Copy link

wearepariah commented Oct 22, 2022

Have taken what @drmaxx has suggested above, and written it in python to replace what's currently hardcoded in to the consts.py file for this plugin. So long as they don't go changing the urls/response format, this should keep itself updated rather than needing a code change each time the APP_ID/GENOME_ID changes.
EDIT: notice that @KS-HTK suggested this as an option earlier - tested and seems to work on my machine.

import requests
import re
ids_url = 'https://ubisoftconnect.com/invalid'
ids_response = requests.get(ids_url)
regex_ids_response = re.findall('APP_ID.{0,40}|GENOME_ID.{0,40}', ids_response.text) 

ids_result = []
for sub in regex_ids_response:
    sub = sub.replace('"','')
    if ':' in sub:
        ids_result.append(map(str.strip, sub.split(':', 1)))

ids_result = dict(ids_result)

CLUB_APPID = ids_result.get('APP_ID','')
CLUB_GENOME_ID = ids_result.get('GENOME_ID','')

Copy link

@wearepariah wearepariah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import requests
ids_url = 'https://ubisoftconnect.com/invalid'
ids_response = requests.get(ids_url)
regex_ids_response = re.findall('APP_ID.{0,40}|GENOME_ID.{0,40}', ids_response.text) 

ids_result = []
for sub in regex_ids_response:
    sub = sub.replace('"','')
    if ':' in sub:
        ids_result.append(map(str.strip, sub.split(':', 1)))

ids_result = dict(ids_result)

CLUB_APPID = ids_result.get('APP_ID','')
CLUB_GENOME_ID = ids_result.get('GENOME_ID','')

@KS-HTK
Copy link

KS-HTK commented Oct 23, 2022

import requests
ids_url = 'https://ubisoftconnect.com/invalid'
ids_response = requests.get(ids_url)
regex_ids_response = re.findall('APP_ID.{0,40}|GENOME_ID.{0,40}', ids_response.text) 

ids_result = []
for sub in regex_ids_response:
    sub = sub.replace('"','')
    if ':' in sub:
        ids_result.append(map(str.strip, sub.split(':', 1)))

ids_result = dict(ids_result)

CLUB_APPID = ids_result.get('APP_ID','')
CLUB_GENOME_ID = ids_result.get('GENOME_ID','')

Thanks for implementing it. That is exactly what I suggested doing, just did not have the time yet.
A minor change that i would suggest is wrapping it in a try, in case of connection error:

import requests
ids_url = 'https://ubisoftconnect.com/invalid'
try:
  ids_response = requests.get(ids_url)
  regex_ids_response = re.findall('APP_ID.{0,40}|GENOME_ID.{0,40}', ids_response.text) 
  ids_result = []
 
  for sub in regex_ids_response:
      sub = sub.replace('"','')
      if ':' in sub:
          ids_result.append(map(str.strip, sub.split(':', 1)))
  
  ids_result = dict(ids_result)
  
  CLUB_APPID = ids_result.get('APP_ID','')
  CLUB_GENOME_ID = ids_result.get('GENOME_ID','')
except requests.exceptions.ConnectionError:
  CLUB_APPID = "314d4fef-e568-454a-ae06-43e3bece12a6"
  CLUB_GENOME_ID = "85c31714-0941-4876-a18d-2c7e9dce8d40"

but then again, if fetching the url does not work, there should be no connection anyway, so maybe this is unnecessary.

Now lets hope that it will eventually be merged.

EDIT: @wearepariah I suggest you should submit it as a PR to @fl4shback fork of this repo.

@wearepariah
Copy link

thanks @KS-HTK - i have created the pull request to @fl4shback repo.
I did think about a try/except for connection errors as you suggested, but if the connection errors out and it falls back to last-hardcoded value, it puts us back where we are now (with needing to update the hardcodes frequently), and like you said - if the connection errors, it's going to fail regardless.
i don't see value in it, but something to capture the error might be good?

@KS-HTK
Copy link

KS-HTK commented Oct 24, 2022

also this should close #35 and #42

@turbo25
Copy link

turbo25 commented Oct 24, 2022

thanks @KS-HTK - i have created the pull request to @fl4shback repo. I did think about a try/except for connection errors as you suggested, but if the connection errors out and it falls back to last-hardcoded value, it puts us back where we are now (with needing to update the hardcodes frequently), and like you said - if the connection errors, it's going to fail regardless. i don't see value in it, but something to capture the error might be good?

import requests
ids_url = 'https://ubisoftconnect.com/invalid'
old_app_id = CLUB_APPID
old_genome_id = CLUB_GENOME_ID
try:
  ids_response = requests.get(ids_url)
  regex_ids_response = re.findall('APP_ID.{0,40}|GENOME_ID.{0,40}', ids_response.text) 
  ids_result = []
 
  for sub in regex_ids_response:
      sub = sub.replace('"','')
      if ':' in sub:
          ids_result.append(map(str.strip, sub.split(':', 1)))
  
  ids_result = dict(ids_result)
  
  CLUB_APPID = ids_result.get('APP_ID','')
  CLUB_GENOME_ID = ids_result.get('GENOME_ID','')
except requests.exceptions.ConnectionError:
  CLUB_APPID = old_app_id
  CLUB_GENOME_ID = old_genome_id

Maybe this can do the trick?

@KS-HTK
Copy link

KS-HTK commented Oct 24, 2022

[…]

import requests
ids_url = 'https://ubisoftconnect.com/invalid'
old_app_id = CLUB_APPID
old_genome_id = CLUB_GENOME_ID
try:
  […]
  
  CLUB_APPID = ids_result.get('APP_ID','')
  CLUB_GENOME_ID = ids_result.get('GENOME_ID','')
except requests.exceptions.ConnectionError:
  CLUB_APPID = old_app_id
  CLUB_GENOME_ID = old_genome_id

Maybe this can do the trick?

No it won't. It would require saving them to a file.
You now assign CLUB_APPID to old_app_id before CLUB_APPID is even initialized.
so you cant store them in a variable between runtimes, as this is not how variables work.

@SpikeBadguy
Copy link

import requests
ids_url = 'https://ubisoftconnect.com/invalid'
ids_response = requests.get(ids_url)
regex_ids_response = re.findall('APP_ID.{0,40}|GENOME_ID.{0,40}', ids_response.text) 

ids_result = []
for sub in regex_ids_response:
    sub = sub.replace('"','')
    if ':' in sub:
        ids_result.append(map(str.strip, sub.split(':', 1)))

ids_result = dict(ids_result)

CLUB_APPID = ids_result.get('APP_ID','')
CLUB_GENOME_ID = ids_result.get('GENOME_ID','')

I tried this but now the add-on is constantly timing out. What did I do wrong?

@KS-HTK
Copy link

KS-HTK commented Oct 26, 2022

I tried this but now the add-on is constantly timing out. What did I do wrong?

Difficult to say without seeing how you modified consts.py
But here is a link to the full file: https://github.com/wearepariah/galaxy-integration-uplay/blob/master/src/consts.py

try replacing yours with that one.

@SpikeBadguy
Copy link

I tried this but now the add-on is constantly timing out. What did I do wrong?

Difficult to say without seeing how you modified consts.py But here is a link to the full file: https://github.com/wearepariah/galaxy-integration-uplay/blob/master/src/consts.py

try replacing yours with that one.

That helped Me fix it. Thanks! I believe I was missing a couple of lines at the top.

@JokeDeity
Copy link

I tried this but now the add-on is constantly timing out. What did I do wrong?

Difficult to say without seeing how you modified consts.py But here is a link to the full file: https://github.com/wearepariah/galaxy-integration-uplay/blob/master/src/consts.py

try replacing yours with that one.

This works much longer for me, but it's not a permanent fix. After a few hours I must reconnect (including pulling out my goddamn phone for the stupid 2 factor authentication). Before it would instantly disconnect in a second after connecting, so this new consts.py is much better, but not a real full solution.

@wearepariah
Copy link

I tried this but now the add-on is constantly timing out. What did I do wrong?

Difficult to say without seeing how you modified consts.py But here is a link to the full file: https://github.com/wearepariah/galaxy-integration-uplay/blob/master/src/consts.py

try replacing yours with that one.

This works much longer for me, but it's not a permanent fix. After a few hours I must reconnect (including pulling out my goddamn phone for the stupid 2 factor authentication). Before it would instantly disconnect in a second after connecting, so this new consts.py is much better, but not a real full solution.

I am not sure that's caused by this change, the constant changing of the ID's could indicate that Ubi have changed something else at their end causing this - the Ubisoft Connect app on my machine has forced me to log back in a bunch of times in the past week, correlation in timing rather than causation.

@KS-HTK
Copy link

KS-HTK commented Nov 1, 2022

No, this is not a fix for a disconnect every 5-6h this is a fix for not being able to connect at all.
I get those spaced out disconnects as well. I guess the reason is because that is when the api key for the account runs out and is not auto renewed by this plugin. (gussing they are using OAUTH2 control flow) I have not had time to look further into it though.
I had asked ubisoft support for a developer api as they do have a section in the accounts page for 3rd party apps. But there is currently no public developer api. And trying to capture the instance when ubisoft connect refetches the key is going to be a heck of a job, as this only happens when the key runs out.

I am not sure there is going to be a fix for that any time soon.

@Icemasta
Copy link

I am about to make the most useless of comments but I got fed up that Ubisoft wasn't showing up in my GoG library so I decided to dig a bit. I verified Backend.py and it does support OAUTH2 and it does handle refreshing tokens already, but I've noticed disconnection there.

I have looked through some of my logs and the originator of the issue seems to begin from a call to _do_safe_request which receives a weird answer. Not wanting to wait, I decided to log to file the tokens and expiry dates, and to subtract a good chunk of time from expiry time.... and it just called _refresh_auth properly? And then again and again and again. So using the fix by @wearepariah in combination by just refreshing the token long before it expires, I seem to be doing good. There is no refresh token rotation. Always the same refresh token.

Now, I am not sure what happens if I turn off GoG for a couple of hours, but combing through the code I've found a couple potential issues, the main ones revolving around improper handling of errors on requests.

We have 3 layers of requests.

We have request which handles the actual request. If it fails, it raises an error, it uses an handle_exception function.

We have _do_request which is a wrapper around request, it has zero error handling.

We have _do_safe_request which is a wrapper around _do_request. It has a preemptive ticket refresh (which is what I used) and a try/except situation to refresh auth but only on AccessDenied, AuthenticationRequired errors, as defined by handle_exception, any errors outside of those 2 is a dead end.

My take aways right now are: Gotta refactor requests so that they always fallback to refreshing auth if it fails and if that fails, kill stored credentials. Request and _do_request are called and can cause this situation. There will probably need to be some method of fallback for exceptions. Some errors I've noticed is that a request returns 401 but the handle_exception doesn't know what to do with it, so it returns unknown handle. We do have situations where we get 401 while doing a token refresh.

Oh and for some reasons _do_options_request has an hardcoded appID

@turbo25
Copy link

turbo25 commented Nov 26, 2022

I am about to make the most useless of comments but I got fed up that Ubisoft wasn't showing up in my GoG library so I decided to dig a bit. I verified Backend.py and it does support OAUTH2 and it does handle refreshing tokens already, but I've noticed disconnection there.

I have looked through some of my logs and the originator of the issue seems to begin from a call to _do_safe_request which receives a weird answer. Not wanting to wait, I decided to log to file the tokens and expiry dates, and to subtract a good chunk of time from expiry time.... and it just called _refresh_auth properly? And then again and again and again. So using the fix by @wearepariah in combination by just refreshing the token long before it expires, I seem to be doing good. There is no refresh token rotation. Always the same refresh token.

Now, I am not sure what happens if I turn off GoG for a couple of hours, but combing through the code I've found a couple potential issues, the main ones revolving around improper handling of errors on requests.

We have 3 layers of requests.

We have request which handles the actual request. If it fails, it raises an error, it uses an handle_exception function.

We have _do_request which is a wrapper around request, it has zero error handling.

We have _do_safe_request which is a wrapper around _do_request. It has a preemptive ticket refresh (which is what I used) and a try/except situation to refresh auth but only on AccessDenied, AuthenticationRequired errors, as defined by handle_exception, any errors outside of those 2 is a dead end.

My take aways right now are: Gotta refactor requests so that they always fallback to refreshing auth if it fails and if that fails, kill stored credentials. Request and _do_request are called and can cause this situation. There will probably need to be some method of fallback for exceptions. Some errors I've noticed is that a request returns 401 but the handle_exception doesn't know what to do with it, so it returns unknown handle. We do have situations where we get 401 while doing a token refresh.

Oh and for some reasons _do_options_request has an hardcoded appID

This is one of the most useful comments instead, but I agree, it's also useless because we have no control on the PRs and merges so these changes will never go live for anyone

@KS-HTK
Copy link

KS-HTK commented Nov 27, 2022

This is one of the most useful comments instead, but I agree, it's also useless because we have no control on the PRs and merges so these changes will never go live for anyone

We do not on this repo. But you could pull a different fork with some of the fixes and manually do git pull if it has an update. I use @fl4shback 's fork instead of this one.

@fl4shback
Copy link
Author

FYI It's been one full (fun) year, I'm pulling the plug on this. Set my repo to archive mode, won't research any future fixes.
I don't use Galaxy anymore, went back to Playnite.

Good luck to those who choose to keep using Galaxy 😄

More info here if you want:
Mixaill/awesome-gog-galaxy#126 (comment)

Copy link

@ColinAvrech ColinAvrech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

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

Successfully merging this pull request may close these issues.

Uplay connection keeps disconnecting