Skip to content

Instantly share code, notes, and snippets.

@matthewroche
Created April 17, 2022 06:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewroche/a551b32126608c816825746fc842389f to your computer and use it in GitHub Desktop.
Save matthewroche/a551b32126608c816825746fc842389f to your computer and use it in GitHub Desktop.
Python OAuth flow for Intervals.icu Lambda
import os
from base64 import b64decode
# Handles a call from the intervals.icu OauthAPI, requests the auth token and returns this in a redirect URL
def lambda_handler(event, context):
# Generic error object to handle errors
def createErrorObject(reason):
return {
'statusCode': 301,
'headers': {
'Location': f'intervalsapp:login?error=true&reason={reason}'
}
}
# Ensure query parameters exist
if not 'queryStringParameters' in event:
return createErrorObject("No queryStringParameters")
qsp = event['queryStringParameters']
# Ensure there is a code in the query string parameters
if not 'code' in qsp:
return createErrorObject("No code available")
code = qsp['code']
client_secret = os.environ['client_secret']
# Construct the call back to the intervals.icu server
url = 'https://intervals.icu/api/oauth/token'
data = {
'client_id': 12,
'client_secret': client_secret,
'code': code
}
# Send the request
http = urllib3.PoolManager()
response = http.request(
'POST',
url,
fields=data
)
print(response.status)
# Ensure the request was successful
if response.status == 200:
# Parse the json response
response_dict = json.loads(response.data.decode('utf-8'))
# Ensure all fields are present
if not 'token_type' in response_dict:
return createErrorObject("No token_type")
if not 'access_token' in response_dict:
return createErrorObject("No access_token")
if not 'scope' in response_dict:
return createErrorObject("No scope")
if not 'athlete' in response_dict:
return createErrorObject("No athlete")
if not 'id' in response_dict['athlete']:
return createErrorObject("No id")
if not 'name' in response_dict['athlete']:
return createErrorObject("No name")
# Obtain the fields
token_type = response_dict['token_type']
access_token = response_dict['access_token']
scope = response_dict['scope']
athlete_id = response_dict['athlete']['id']
athlete_name = response_dict['athlete']['name']
# Create redirect response
return {
'statusCode': 301,
'headers': {
'Location': f'intervalsapp:login?token_type={token_type}&access_token={access_token}&scope={scope}&athlete_id={athlete_id}&athlete_name={athlete_name}'
}
}
else:
# Handle invalid response from server
return createErrorObject(f"Incorrect response from server: {response.status}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment