Aggregating the bagging.
I followed these instructions to register an API application for Strava. These docs helped me to understand the OAuth 2.0 flow with Strava.
Signed in, I grabbed my client ID and secret from this page. Annoyingly, like a lot of other implementations of OAuth 2.0 flows, Strava requires a bit of a workaround to generate access and refresh tokens for the first time if you are building an API-driven application. After I have stored an initial refresh token, I am able to programmatically get a new, refreshed access token before each batch of Strava API requests.
Note that the default access and refresh tokens provided by Strava (which can be grabbed from the "My API Application"
page) only have read
scope which is not sufficient for getting detailed information about an activity.
I pasted the following into my browser (note the read_all
scope):
https://www.strava.com/oauth/authorize?client_id=17865&response_type=code&redirect_uri=http://localhost/exchange_token&approval_prompt=force&scope=activity:read_all
Clicked "Authorize" when prompted.
Was taken to something like:
https://localhost/exchange_token?state=&code=152aae17e171b3d122e240198f4b965ccf5f6463&scope=read,activity:read_all
Extracted the authorization code (152aae17e171b3d122e240198f4b965ccf5f6463
, in this case).
Exchanged the code for an access (and refresh) token using my client secret:
curl -X POST https://www.strava.com/oauth/token -F client_id=17865 -F client_secret=${my client secret} -F code=152aae17e171b3d122e240198f4b965ccf5f6463 -F grant_type=authorization_code
From the response, I grabbed the refresh_token
.
I used the AWS CLI to upload the initial refresh token to AWS Secrets Manager. For example:
aws secretsmanager update-secret --secret-id strava-refresh-token --secret-string d4e8ee7a4103a7eedbbc9346f86aca0ab1c67aeb
Subsequent refresh tokens will be programmatically fetched (from Strava's API) and stored (in AWS Secrets Manager) by the Lambda function. Note that previous refresh tokens are immediately invalidated upon the successful issue of a new one.
Strava access tokens expire after six hours. I intend for the Lambda function to execute at most once per day, so I have designed the function to always fetch new tokens before trying to make a request to the Strava API.
The relevant Strava documentation says:
To refresh an access token, applications should call the POST https://www.strava.com/oauth/token endpoint, specifying grant_type: refresh_token and including the application’s refresh token for the user as an additional parameter. If the application has an access token for the user that expires in more than one hour, the existing access token will be returned. If the application’s access tokens for the user are expired or will expire in one hour (3,600 seconds) or less, a new access token will be returned. In this case, both the newer and older access tokens can be used until they expire.
A refresh token is issued back to the application after all successful requests to the POST https://www.strava.com/oauth/token endpoint. The refresh token may or may not be the same refresh token used to make the request. Applications should persist the refresh token contained in the response, and always use the most recent refresh token for subsequent requests to obtain a new access token. Once a new refresh token is returned, the older refresh token is invalidated immediately.
- Loop through pages of activities (from the
/athlete
API) until they are exhausted - Make a list of activity IDs that have
#munros
in the name - Use the
/activities
API to get detailed information about each activity
- Check for the existence of a
munros.json
in the bucket - If it exists, copy it and suffix it with a timestamp
- Over/write
munros.json
with the latest Munro-related activities from Strava