Skip to content

Commit

Permalink
Merge pull request #102 from PlaidWeb/feature/101-twitter-userid
Browse files Browse the repository at this point in the history
Switch to twitter /i/user endpoint for Twitter identity URLs, add profile_url field
  • Loading branch information
fluffy-critter committed Oct 14, 2021
2 parents b66bff2 + 2894929 commit 28e5d9e
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 65 deletions.
3 changes: 3 additions & 0 deletions authl/disposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ class Verified(Disposition):
* ``location``: The user's stated location
* ``name``: The user's display/familiar name
* ``pronouns``: The user's declared pronouns
* ``profile_url``: A human-readable URL to link to the user's
service-specific profile (which may or may not be the same as their
identity URL).
* ``endpoints``: A dictionary of key-value pairs referring to the user's
various integration services
Expand Down
2 changes: 1 addition & 1 deletion authl/handlers/email_addr.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ def from_config(config, token_store: tokens.TokenStore):
)
send_func = simple_sendmail(connector, config['EMAIL_FROM'], config['EMAIL_SUBJECT'])

check_message = config.get('EMAIL_CHECK_MESSAGE', 'Check your email for a login link')
check_message = config.get('EMAIL_CHECK_MESSAGE', 'Check your email for a login link.')

if 'EMAIL_TEMPLATE_FILE' in config:
with open(config['EMAIL_TEMPLATE_FILE'], encoding='utf-8') as file:
Expand Down
1 change: 1 addition & 0 deletions authl/handlers/fediverse.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ def initiate_auth(self, id_url, callback_uri, redir):

# mastodon.py doesn't support a state parameter for some reason, so we
# have to add it ourselves
# pylint:disable=consider-using-f-string
url = '{}&{}'.format(
client.auth_request_url(
redirect_uris=callback_uri,
Expand Down
2 changes: 1 addition & 1 deletion authl/handlers/indieauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ def check_callback(self, url, get, data):

if request.status_code != 200:
LOGGER.error("Request returned code %d: %s", request.status_code, request.text)
return disposition.Error("Authorization endpoint returned %d" % request.status_code,
return disposition.Error(f"Authorization endpoint returned {request.status_code}",
redir)

try:
Expand Down
6 changes: 3 additions & 3 deletions authl/handlers/twitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,7 @@ def check_callback(self, url, get, data):
LOGGER.log(logging.WARNING if 'errors' in user_info else logging.NOTSET,
"User profile showed error: %s", user_info.get('errors'))
return disposition.Verified(
# We include the user ID after the hash code to prevent folks from
# logging in by taking over a username that someone changed/abandoned.
f'https://twitter.com/{user_info["screen_name"]}#{user_info["id_str"]}',
f'https://twitter.com/i/user/{user_info["id_str"]}',
redir,
self.build_profile(user_info))
except Exception as err: # pylint:disable=broad-except
Expand Down Expand Up @@ -207,6 +205,8 @@ def expand_entities(name):
profile = {p_key: expand_entities(t_key)
for p_key, t_key in mapping if t_key in user_info}

profile['profile_url'] = f'https://twitter.com/{user_info["screen_name"]}'

# attempt to get a more suitable image
if 'avatar' in profile:
for rendition in ('_400x400', ''):
Expand Down
106 changes: 53 additions & 53 deletions poetry.lock

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions tests/handlers/test_emailaddr.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ def do_callback(message):
LOGGER.info('check_callback(%s,%s): %s', url, args, result)

assert isinstance(result, disposition.Verified)
assert result.identity == 'mailto:user@example.com'
assert result.redir == '/redir'
store['result'] = result

store['is_done'] = result.identity

handler = email_addr.EmailAddress(do_callback, 'some data', tokens.DictStore(store),
email_template_text='{url}')
Expand All @@ -79,6 +80,9 @@ def do_callback(message):
assert isinstance(result, disposition.Notify)
assert result.cdata == 'some data'

assert store['result'].identity == 'mailto:user@example.com'
assert store['result'].redir == '/redir'


def test_failures(mocker):
store = {}
Expand Down
13 changes: 8 additions & 5 deletions tests/handlers/test_twitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@ def test_auth_success(mocker, requests_mock):
'oauth_token_secret': 'my_secret'
}

result = handler.initiate_auth('https://twitter.com/fluffy', 'http://cb', 'redir')
result = handler.initiate_auth('https://twitter.com/fakeinput', 'http://cb', 'redir')

assert isinstance(result, disposition.Redirect), str(result)
assert result.url.startswith('https://api.twitter.com')

args = parse_args(result.url)
print(result.url)
assert args['screen_name'] == 'fluffy'
assert args['screen_name'] == 'fakeinput'
assert args['oauth_token'] == 'my_token'
assert 'my_token' in storage

Expand All @@ -90,7 +90,8 @@ def test_auth_success(mocker, requests_mock):
result = handler.check_callback('foo', args, {})
assert isinstance(result, disposition.Verified), str(result)
assert result.redir == 'redir'
assert result.identity == 'https://twitter.com/foo#12345'
assert result.identity == 'https://twitter.com/i/user/12345'
assert result.profile['profile_url'] == 'https://twitter.com/foo'

# guard against replay attacks
result = handler.check_callback('foo', args, {})
Expand Down Expand Up @@ -185,7 +186,8 @@ def test_profile(requests_mock):
{'url': 'https://is.gd/notareallink', 'expanded_url': 'https://beesbuzz.biz/'}
]
}
}
},
'screen_name': 'qwerpoiufojar',
}

requests_mock.head('http://example.com/foo_400x400.jpg', status_code=200)
Expand All @@ -194,5 +196,6 @@ def test_profile(requests_mock):
profile = handler.build_profile(user_info)
assert profile == {
'avatar': 'http://example.com/foo_400x400.jpg',
'bio': 'this is a biography. see more at https://beesbuzz.biz/'
'bio': 'this is a biography. see more at https://beesbuzz.biz/',
'profile_url': 'https://twitter.com/qwerpoiufojar',
}

0 comments on commit 28e5d9e

Please sign in to comment.