Infinity-For-Reddit icon indicating copy to clipboard operation
Infinity-For-Reddit copied to clipboard

Infinity cannot login anymore

Open 7heo opened this issue 2 years ago • 4 comments

Checklist

  • [X] I have used the search function for open and closed issues to see if someone else has already submitted the same bug report.
  • [X] I will describe the problem with as much detail as possible.
  • [X] If the bug only occurs with a certain link, post, image..., I will include the URL.

App version

5.4.2

Where did you get the app from

F-Droid

Android version

8.1.0

First occurred

Today

Steps to reproduce

  1. Log out of your currently logged in account
  2. Tap "Add an account" in the main menu, under "Press here to login"
  3. Agree to the ToS
  4. Login
  5. Accept the permission grant for "Infinity for Reddit"

Expected behaviour

The InfinityForReddit app should grab the proper response via https://github.com/Docile-Alligator/Infinity-For-Reddit/blob/master/app/src/main/java/ml/docilealligator/infinityforreddit/activities/LoginActivity.java#L186 and close the in-app browser once the values are obtained.

Current behaviour

~~A white page is displayed in the in-app browser, with a blue menu (showing entries like "Coins", "Premium", "Powerups", etc) featuring a "Sign up or log in" button. The login process is stalled.~~ The "Welcome back!" page redirects to itself infinitely. Probably because of the name of the app.

7heo avatar May 31 '23 15:05 7heo

Just so we're clear, I do not think this bug is necessarily solely because of Infinity. If the reddit servers are returning an unexpected answer, this behavior could totally happen.

However, the error handling implementation is currently absent from the app's code, and this could possibly also be caused by Infinity-For-Reddit not having kept up with some recent API changes.

7heo avatar May 31 '23 16:05 7heo

I had a strange issue with it where I couldn't send messages. I had to remove the account from Infinity, but I was able to log in as of the latest update.

Alvie avatar Jun 01 '23 14:06 Alvie

So I did a bit of testing with the following python script:

#!/usr/bin/env python
"""Infinity simulation script, for debugging purposes"""

from base64 import b64encode
from json import dumps
from json import loads
from json.decoder import JSONDecodeError
from os import remove
from os import system
from socket import AF_UNIX
from socket import SOCK_DGRAM
from socket import socket
from sys import argv
from sys import exit as sysexit
from sys import stderr
from urllib.parse import urlencode
from requests import post

DEBUG = True
BROWSER = "x-www-browser"
SOCKPATH = "/tmp/infinity-debug.sock"
PROGNAME = "infinity-debug"

CLIENT_ID = "NOe2iKrPPzwscA"
STATE = "23ro8xlxvzp4asqd"
REDIRECT_URI = "infinity://localhost"


def debug_print(msg):
  """Print the debug message, if DEBUG is True"""
  if DEBUG:
    print(msg, file=stderr)


def process(args):
  """Process the response from the reddit API"""
  try:
    host, data = args[0].split('?')
    if host != REDIRECT_URI:
      raise ValueError(f"Malformed host '{host}'")
    params = dict((i.split('=') for i in data.split('&')))
  except KeyError:
    print(f"ERROR: Received incorrectly formatted data '{data}'", file=stderr)
  except ValueError as _e:
    print(f"ERROR: {_e}", file=stderr)
  if 'code' in params:
    code = params['code']
    state = params['state']
    if state != STATE:
      print("Received state {state} was different than expected state {STATE}",
            file=stderr)
      return
    base_uri = "https://www.reddit.com/api/v1/access_token"
    params = {}
    params["grant_type"] = "authorization_code"
    params["code"] = code
    params["redirect_uri"] = REDIRECT_URI
    creds = f"{CLIENT_ID:}"
    auth_header = {"Authorization":
                   f"Basic {b64encode(creds.encode('ascii')).decode('ascii')}"}
    debug_print(f"POST {base_uri} with {urlencode(params)}"
                f"and header {auth_header}")
    resp = loads(post(f"{base_uri}",
                      data=params,
                      headers=auth_header,
                      timeout=500).text)
    print(f"Got JSON: {resp}")


def main():
  """Main function"""
  if len(argv) == 1:
    base_uri = "https://www.reddit.com/api/v1/authorize.compact"
    params = {}
    params["client_id"] = CLIENT_ID
    params["response_type"] = "code"
    params["state"] = STATE
    params["redirect_uri"] = REDIRECT_URI
    params["duration"] = "permanent"
    params["scope"] = ("identity edit flair history modconfig modflair modlog "
                       "modposts modwiki mysubreddits privatemessages read "
                       "report save submit subscribe vote wikiedit wikiread "
                       "creddits modcontributors modmail modothers livemanage "
                       "account modself")
    debug_print(f"{BROWSER} {base_uri}?{urlencode(params)}")
    system(f"{BROWSER} {base_uri}?{urlencode(params)}")

    sock = socket(AF_UNIX, SOCK_DGRAM)
    try:
      sock.connect(SOCKPATH)
      print(f"Another instance of {PROGNAME} is already running.", file=stderr)
    except ConnectionRefusedError:
      remove(SOCKPATH)
    except FileNotFoundError:
      pass
    sock.bind(SOCKPATH)

    loop = True
    while loop:
      try:
        data = sock.recv(2048)
        if data:
          try:
            process(loads(data.decode('utf-8')))
          except JSONDecodeError:
            print(f"WARNING: Malformed JSON data received ({data}).",
                  file=stderr)
      except KeyboardInterrupt:
        loop = False

    print("Exitting...", file=stderr)
    sock.close()
    remove(SOCKPATH)
  else:
    sock = socket(AF_UNIX, SOCK_DGRAM)
    try:
      sock.connect(SOCKPATH)
    except (FileNotFoundError, ConnectionRefusedError):
      print(f"ERROR: The main {PROGNAME} process isn't running.", file=stderr)
      try:
        input("Press enter to continue...")
      except KeyboardInterrupt:
        pass
      sysexit(1)
    sock.send(dumps(argv[1:]).encode('utf-8'))


if __name__ == "__main__":
  main()

to simulate the flow of the Infinity app, and on my first try, I got 429 Too Many Requests once, and promptly after, 401 Unauthorized, both as an HTTP error and in the JSON payload, as if the client ID had been revoked. I had these responses twice, yesterday and today. I even tested with curl to make sure this was consistent, and it is.

I now suspect that the reddit API has become intentionally uncooperative.

On a totally unrelated note, it would be worth reporting the error properly (parsing eventual HTTP error codes and the JSON answer for display) in Infinity for reddit client. Or, maybe the entire project can be cancelled, now that reddit is playing the apart*eid billionaire neona*i game... :unamused: (asterisks because I don't trust Microsoft to play ball on that one, and this comment could still help people)

7heo avatar Jun 01 '23 16:06 7heo

Interestingly enough, now that I tried again, the login page does not redirect to the client authorization page anymore, it seems. Instead, it loops onto the "Welcome back!" page. But when using curl to directly access the /api/v1/access_token end point, the JSON errors can still be accessed. All one needs is a valid code (which cannot be obtained anymore, due to the first call redirecting to the same page infinitely) and the following command:

printf 'grant_type=authorization_code&redirect_uri=infinity://localhost&code=****************************' \
| curl -v -d@- -H 'Authorization: Basic Tk9lMmlLclBQendzY0E6Cg==' https://www.reddit.com/api/v1/access_token

7heo avatar Jun 01 '23 16:06 7heo

This is not fixed.

I have Infinity 6.3.1 from f-droid, and when I attempt to login, I get: "There was an error trying to connect with your reddit account".

With the following error:

Error: Invalid request to OAuth API

7heo avatar Dec 14 '23 13:12 7heo