Skip to content

Commit

Permalink
Use CSRF in updated SSO protocol #14, fixes #13
Browse files Browse the repository at this point in the history
  • Loading branch information
Bastien Abadie authored Apr 23, 2019
2 parents 3240c4c + 8d20d70 commit 8320b01
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Garmin Uploader (aka gupload), uploads files
(.tcx, .gpx, and .fit files ) created by Garmin fitness
devices to the http://connect.garmin.com web site.

:star: Yes, it works with the latest (April 2018) Garmin connect authentication update.
:star: Yes, it works with the latest (~~April 2018~~ April 2019) Garmin connect authentication update.

This is an up to date version of [GCPUploader](https://github.com/dlotton/GcpUploader) by Dave Lotton. Thanks Dave for creating this tool :+1:

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.6
1.0.7~beta
32 changes: 20 additions & 12 deletions garmin_uploader/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
URL_PROFILE = 'https://connect.garmin.com/modern/proxy/userprofile-service/socialProfile/' # noqa
URL_HOST_SSO = 'sso.garmin.com'
URL_HOST_CONNECT = 'connect.garmin.com'
URL_SSO_SIGNIN = 'https://sso.garmin.com/sso/signin'
URL_UPLOAD = 'https://connect.garmin.com/modern/proxy/upload-service/upload'
URL_ACTIVITY_BASE = 'https://connect.garmin.com/modern/proxy/activity-service/activity' # noqa
URL_ACTIVITY_TYPES = 'https://connect.garmin.com/modern/proxy/activity-service/activity/activityTypes' # noqa
Expand Down Expand Up @@ -65,41 +66,52 @@ def authenticate(self, username, password):
'displayNameShown': 'false',
'embedWidget': 'false',
'gauthHost': 'https://sso.garmin.com/sso',
'generateExtraServiceTicket': 'false',
'generateExtraServiceTicket': 'true',
'generateNoServiceTicket': 'false',
'generateTwoExtraServiceTickets': 'false',
'globalOptInChecked': 'false',
'globalOptInShown': 'false',
'globalOptInShown': 'true',
'id': 'gauth-widget',
'initialFocus': 'true',
'locale': 'fr',
'locationPromptShown': 'true',
'mobile': 'false',
'openCreateAccount': 'false',
'privacyStatementUrl': '//connect.garmin.com/fr-FR/privacy/',
'privacyStatementUrl': 'https://www.garmin.com/fr/privacy/connect/', # noqa
'redirectAfterAccountCreationUrl': 'https://connect.garmin.com/modern/', # noqa
'redirectAfterAccountLoginUrl': 'https://connect.garmin.com/modern/', # noqa
'rememberMeChecked': 'false',
'rememberMeShown': 'true',
'service': 'https://connect.garmin.com/modern/',
'source': 'https://connect.garmin.com/fr-FR/signin',
'usernameShown': 'false',
'webhost': sso_hostname
'showPassword': 'true',
'source': 'https://connect.garmin.com/signin/',
'webhost': sso_hostname,
}

res = session.get(URL_LOGIN, params=params)
if res.status_code != 200:
raise Exception('No login form')

# Lookup for CSRF token
csrf = re.search(r'<input type="hidden" name="_csrf" value="(\w+)" />', res.content.decode('utf-8')) # noqa
if csrf is None:
raise Exception('No CSRF token')
csrf_token = csrf.group(1)
logger.debug('Found CSRF token {}'.format(csrf_token))

# Login/Password with login ticket
data = {
'embed': 'false',
'username': username,
'password': password,
'_csrf': csrf_token,
}
headers = {
'Host': URL_HOST_SSO,
'Referer': URL_SSO_SIGNIN,
}
res = session.post(URL_LOGIN, params=params, data=data,
headers=headers)
if res.status_code != 200:
if not res.ok:
raise Exception('Authentification failed.')

# Check we have sso guid in cookies
Expand All @@ -124,10 +136,6 @@ def authenticate(self, username, password):
if res.status_code != 200 and not res.history:
raise Exception('Second auth step failed.')

# Check session cookie
if 'JSESSIONID' not in session.cookies:
raise Exception('Missing session auth cookie')

# Check login
res = session.get(URL_PROFILE)
if not res.ok:
Expand Down

0 comments on commit 8320b01

Please sign in to comment.