Authentication

Strava uses OAuth 2.0 for authentication. This guide covers the complete authorization flow, permission scopes, and token management.

OAuth 2.0 Flow Overview

The OAuth flow allows users to grant your application access to their Strava data without sharing their password. Here's how it works:

  1. 1

    Redirect to Strava

    Your app redirects the user to Strava's authorization page

  2. 2

    User Grants Permission

    User logs in and approves the requested permissions (scopes)

  3. 3

    Receive Authorization Code

    Strava redirects back to your app with a temporary authorization code

  4. 4

    Exchange for Tokens

    Your server exchanges the code for access and refresh tokens

Step 1: Redirect to Authorization URL

Construct the authorization URL and redirect users to it:

https://www.strava.com/oauth/authorize?
  client_id=YOUR_CLIENT_ID&
  redirect_uri=YOUR_CALLBACK_URL&
  response_type=code&
  scope=read,activity:read_all
ParameterDescription
client_idYour application's Client ID
redirect_uriURL to redirect to after authorization (must match your app settings)
response_typeMust be code
scopeComma-separated list of requested permissions
state(Optional) Random string to prevent CSRF attacks

Permission Scopes

Scopes define what data your app can access. Request only the scopes you need:

ScopeAccess Granted
readPublic segments, routes, profile data, posts, events, club feeds, leaderboards
read_allPrivate routes, segments, and events (in addition to read)
profile:read_allAll profile information, including email and private data
profile:writeUpdate athlete weight, FTP, and star/unstar segments
activity:readActivities visible to "Everyone" or "Followers"
activity:read_allAll activities, including "Only You" and privacy zones
activity:writeCreate manual activities, upload files, and edit activities

Best Practice: Only request the minimum scopes your app needs. Users are more likely to authorize apps that request limited permissions.

Step 2: Exchange Authorization Code for Tokens

After the user authorizes your app, they're redirected to your callback URL with a code parameter. Exchange this code for tokens:

curl -X POST https://www.strava.com/oauth/token \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d code=AUTHORIZATION_CODE \
  -d grant_type=authorization_code

Response

{
  "token_type": "Bearer",
  "expires_at": 1704931200,
  "expires_in": 21600,
  "refresh_token": "REFRESH_TOKEN_HERE",
  "access_token": "ACCESS_TOKEN_HERE",
  "athlete": {
    "id": 12345678,
    "username": "athlete_username",
    "firstname": "John",
    "lastname": "Doe"
  }
}
FieldDescription
access_tokenToken to use for API requests
refresh_tokenToken to get new access tokens (save this securely!)
expires_atUnix timestamp when the access token expires
expires_inSeconds until expiration (6 hours = 21600)

Refreshing Access Tokens

Access tokens expire after 6 hours. Use the refresh token to get a new access token:

curl -X POST https://www.strava.com/oauth/token \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d refresh_token=CURRENT_REFRESH_TOKEN \
  -d grant_type=refresh_token

Important: Refresh Token Rotation

Each refresh request returns a new refresh token. You must save the new refresh token and use it for subsequent refresh requests. The old refresh token becomes invalid.

JavaScript Example

async function refreshAccessToken(refreshToken) {
  const response = await fetch('https://www.strava.com/oauth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      client_id: process.env.STRAVA_CLIENT_ID,
      client_secret: process.env.STRAVA_CLIENT_SECRET,
      refresh_token: refreshToken,
      grant_type: 'refresh_token'
    })
  });

  const data = await response.json();

  // IMPORTANT: Save the new refresh token!
  await saveTokens(data.access_token, data.refresh_token, data.expires_at);

  return data.access_token;
}

Deauthorization

Users can revoke access from their Strava settings, or your app can programmatically deauthorize:

curl -X POST https://www.strava.com/oauth/deauthorize \
  -H "Authorization: Bearer ACCESS_TOKEN"

This invalidates all tokens and removes your app from the athlete's authorized applications.