Strava: Authorization Error - Missing activity:read_permission
I’m revisiting the Strava API after a two year absence and the approach to authenticating requests has changed in that time. You now need to generate an access token via OAuth 2.0, as described in the 'How to authenticate with OAuth 2.0' section of the Getting Started with the Strava API guide.
I want to generate a token that lets me retrieve all of my activities via the /athlete/activities
end point.
I tried to do this by following these steps:
-
Go to https://www.strava.com/settings/api and copy your Client ID
-
Paste your Client ID into this URL: REPLACE_WITH_YOUR_CLIENT_ID&response_type=code&redirect_uri=http://localhost/exchange_token&approval_prompt=force&scope=read
-
Go to a browser
-
Paste the URL you edited into the browser window (step 1 and 2 from the graph)
-
Hit enter
-
When you see the authorization page, click “Authorize” (step 3a from the graph)
Once we click on 'Authorize', the web browser redirects to a localhost URL that contains an authorisation code. For me, this URL looks like this:
http://localhost/exchange_token?state=&code=b55003496d87a9f0b694ca1680cd5690d27d9d28&scope=read
We then take that code and feed it into another request, which will generate a refresh token, access token, and access token expiration date:
curl -X POST https://www.strava.com/oauth/token \
-F client_id=YOURCLIENTID \
-F client_secret=YOURCLIENTSECRET \
-F code=b55003496d87a9f0b694ca1680cd5690d27d9d28 \
-F grant_type=authorization_code
This request will will return a JSON response that looks like this:
{
"token_type": "Bearer",
"expires_at": 1608060738,
"expires_in": 18068,
"refresh_token": "<refresh-token>",
"access_token": "<access-token>",
"athlete": {
"id": 6958432,
"username": null,
"resource_state": 2,
"firstname": "Mark",
"lastname": "Needham",
"city": "London",
"state": "England",
"country": "United Kingdom",
"sex": "M",
"premium": true,
"summit": true,
"created_at": "2014-11-01T10:48:26Z",
"updated_at": "2020-08-10T06:23:51Z",
"badge_type_id": 1,
"profile_medium": "https://dgalywyr863hv.cloudfront.net/pictures/athletes/6958432/17352912/1/medium.jpg",
"profile": "https://dgalywyr863hv.cloudfront.net/pictures/athletes/6958432/17352912/1/large.jpg",
"friend": null,
"follower": null
}
}
We can then take the access_token
and use that on requests against other API endpoints.
For example, to retrieve my activities, we can make the following request:
curl -X GET https://www.strava.com/api/v3/athlete/activities -H 'Authorization: Bearer <access-token>'
When I ran that, I got the following response:
{
"message": "Authorization Error",
"errors": [
{
"resource": "AccessToken",
"field": "activity:read_permission",
"code": "missing"
}
]
}
The mistake I’ve made was right at the beginning of the authentication process, when selecting the 'scope' on the initial request. We used the following URL:
http://www.strava.com/oauth/authorize?client_id=[REPLACE_WITH_YOUR_CLIENT_ID]&response_type=code&redirect_uri=http://localhost/exchange_token&approval_prompt=force&scope=read
The scope
is set to read
when this API end point requires activity:read_all
permissions, so the URL should instead read like this:
http://www.strava.com/oauth/authorize?client_id=[REPLACE_WITH_YOUR_CLIENT_ID]&response_type=code&redirect_uri=http://localhost/exchange_token&approval_prompt=force&scope=activity:read_all
And if we do that and use the authorisation code that it returns to generate an access token, it all works as expected.
Now it’s time to analyse those runs!
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.