Skip to content

Commit

Permalink
Switched to using a Firefox user-agent, and added XSRF token GET call
Browse files Browse the repository at this point in the history
  • Loading branch information
meson800 committed May 4, 2023
1 parent 1b980e9 commit b327a6e
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 14 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.5.2] - 2023-05-04
### Updated
- Switched to using a Firefox user-agent, and added XSRF token GET call.

## [0.5.1] - 2023-02-04
### Updated
- Updated the version of requests-pkcs12 we rely on to avoid deprecation warnings.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,9 @@ having to re-install after each update.
## Changelog
See the [CHANGELOG](CHANGELOG.md) for detailed changes.
```
## [0.5.1] - 2023-02-04
## [0.5.2] - 2023-05-04
### Updated
- Updated the version of requests-pkcs12 we rely on to avoid deprecation warnings.
- Switched to using a Firefox user-agent, and added XSRF token GET call.
```

## License
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name='touchstone-auth',
version='0.5.1',
version='0.5.2',
author='Christopher Johnstone',
author_email='[email protected]',
description='Access Touchstone SSO sites without a web browser.',
Expand Down
33 changes: 22 additions & 11 deletions src/touchstone_auth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def __init__(self,
self._twofactor_type = twofactor_type
self._verbose = verbose
self._session.headers.update({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/112.0'
})
self._autosave_cookies = autosave_cookies

Expand Down Expand Up @@ -226,6 +226,9 @@ def perform_touchstone(self, conversation):
raise TouchstoneError("Initial authentication with {} failed".format(type(self._auth).__name__))
duo_script = duo_container.findChildren('script')[1].string

# Get parent URL
parent_url = r.url

# Clean up json string before decoding
duo_connect_string = re.search(
r'Duo.init\(({[\S\s]*})\);',
Expand All @@ -238,31 +241,39 @@ def perform_touchstone(self, conversation):
# POST to Duo, which will 302 redirect, giving us the prompt SID
duo_connect_params = {
'tx': duo_tx,
'parent': f'https://idp.mit.edu:446/idp/Authn/Certificate?login_certificate=Use+Certificate+-+Go&conversation={conversation}',
'parent': parent_url,
'v': '2.6'
}

auth_request = self._session.post(f"https://{duo_json['host']}/frame/web/v1/auth",
params=duo_connect_params,
data={
duo_prompt_data = {
# Why do we have to provide tx and parent both in params and data? No idea...
'tx': duo_connect_params['tx'],
'parent': duo_connect_params['parent'],
'java_version': '',
'flash_version': '',
'screen_resolution_width': '1920',
'screen_resolution_height': '1080',
'color_depth': '24',
'screen_resolution_width': '2560',
'screen_resolution_height': '1440',
'color_depth': '32',
'ch_ua_error': '',
'client_hints': '',
'is_cef_browser': 'false',
'is_ipad_os': 'false',
'is_ie_compatibility_mode': '',
'is_user_verifying_platform_authenticator_available': '',
'user_verifying_platform_authenticator_available': '',
'is_user_verifying_platform_authenticator_available': 'false',
'user_verifying_platform_authenticator_available_error': '',
'acting_ie_version': '',
'react_support': 'true',
'react_support_error_message': ''
})
}
# Get the URL first to set the xsrf cookie
_xsrf_get = self._session.get(f"https://{duo_json['host']}/frame/web/v1/auth",
params=duo_connect_params
)
# Post to get the redirect
auth_request = self._session.post(f"https://{duo_json['host']}/frame/web/v1/auth",
params=duo_connect_params,
data=duo_prompt_data
)
if len(auth_request.history) > 0:
# A redirect happened, do the full auth flow if we have time to block
if not self._blocking:
Expand Down

0 comments on commit b327a6e

Please sign in to comment.