Intervals.icu OAuth support

Intervals.icu uses OAuth2 for authentication to the API. OAuth allows external applications to request authorization to access an Intervals.icu user’s data. It allows users to grant and revoke API access on a per-application basis and keeps user authentication details safe.

Creating An Application

Please mail the following info to david@intervals.icu:

  • App name
  • Description
  • Website URL
  • Logo image URL
  • Privacy policy URL
  • Redirect URI (http://localhost/ is always allowed)

Contact me (David) via Intervals.icu chat (“Ask a coach” box) and let me know you have sent the mail. This will also indicate who you are on Intervals.icu.

Once your application has been created you will receive a client_id and client_secret. The client_id is public information but the client_secret needs to be carefully protected.

Requesting Authorization To Access Intervals.icu Data For A User

Send the user to:

https://intervals.icu/oauth/authorize?client_id=<your client id>
    &redirect_uri=<your redirect uri>
    &scope=<required scopes>
    &state=<optional data>

Intervals.icu will ask the user to login and display a confirmation dialog with options to choose which
scopes to grant the application. If the user confirms then they are redirected to the redirect_uri with an
authorization code and the optional state parameter:

<your redirect uri>?code=3983ed415f66413c890ca48b7cce59e4&state=...

If they decline:

<your redirect uri>?error=access_denied

Your server needs to exchange the code for an access token within 2 minutes by POSTing form data including your client_id and client_secret:

curl -X POST https://intervals.icu/api/oauth/token \
    -d client_id=...
    -d client_secret=...
    -d code=3983ed415f66413c890ca48b7cce59e4

If all goes well Intervals.icu will respond with an access token, granted scopes and the id and name of the athlete:

{
    "token_type": "Bearer",
    "access_token": "d842c1fc25f241e5ae440d09756448a9",
    "scope": "ACTIVITY:WRITE,WELLNESS:WRITE",
    "athlete": {
        "id": "2049151",
        "name": "David (intervals.icu)"
    }
}   

To call the API use “Authorization: Bearer d842c1fc25f241e5ae440d09756448a9” header. Endpoints will generally also include the athlete id in the path.

Scopes

Scopes are as follows:

  • ACTIVITY: Completed rides, runs etc.
  • WELLNESS: Weight, resting HR etc.
  • CALENDAR: Planned workouts
  • LIBRARY: Workout library
  • SETTINGS: Athlete settings

For each scope specify READ or WRITE (to update, implies READ access) and use commas to separate multiple scopes. Example:

ACTIVITY:READ,WELLNESS:WRITE

Requests read access to activities and read and write access to wellness data.

Your Own Data

Note that you don’t need to do all this if you just want access to your own data. Use your API key to do that.

API Endpoints

3 Likes

This is what a user sees on the /settings page when they have authorised an app:

Note that HealthFit support for Intervals.icu is still in beta.

2 Likes

Hi David -

Just need confirmation. If we want (an app) to allow access to the user’s own data, there isn’t a need to use OAuth correct? Just the basic authentication bit would suffice?

Thanks.

I’m working on possibly integrating my app to connect to intervals.icu’s API

Thanks.

1 Like

Was just about to ask the same question.

Yes if a user is only trying to get at their own data then they can just use basic auth and their API key. However if you are building something for lots of users it is better to do the oauth thing.

1 Like

I need to get my head round the oauth thing in R. If you don’t mind this would be a good test to connect this way to Intervals. I only get about 10 hits a day (EnDuRA is very niche!) plus I’d be sending people you way for full/longitudinal training planning and monitoring. I’ll send the proper request soon.

Cool. Its quite simple really: Just construct correct URL to send users to Intervals.icu to auth, then swap the code that comes back via the redirect URL for an access token.

Thanks. Got a dummy app working with Strava api and oauth last night so think I get it.

Shot. Intervals.icu is a bit easier because it doesn’t use refresh tokens, only access tokens.

1 Like

Is there a limitation for oAuth access to only be limited to one device at any one time?
When I auth using my ipad, i can upload data. But when I do the same to my (already auth) iPhone. I have to re-auth again to be able to upload data.

I’ve never really delve down deeper why this is the case for intervals, DropBox and Strava seems to work for both devices.

Nothing that I am aware of. Intervals.icu only cares that the correct Bearer token is supplied, not where it is coming from.

I’ll check if the token is the same for both devices then.

Just checked. Seems like the Access Token is different between the ipad and the iphone w/ the same login. Is this expected?

Thanks

Hmm. I just had a look at the code and a new token is generated each time a user auths an app and this replaces whatever token might already exist. I could return the existing token if there is one for the app. I wonder if there are any security implications?

For those trying to use this login flow for mobile apps, storing the client secret within your app is a security vulnerability as the secret can be read from the API calls your app makes during the login process. I have developed an AWS Lambda script to proxy the OAuth calls and keep the client secret secure. If this is useful to anyone in the future it is here: Python OAuth flow for Intervals.icu Lambda · GitHub

1 Like

I’ve noticed this to be a problem too David, I can’t see any problem returning an existing token but I’m no security expert…

If I read it correctly, you’re saying that your app (fitnessFatigue) uses this script that is hosted on AWS Lambda to get the accessTokens back to your app?

eg:
Your App → Call Login → Login page triggers the AWS Lambda script → AWS Lambda script executes and then returns the access token → Your App

Is that the flow?

I just took at look at AWS Lambda, basically you need an account as well as pay some amount of money for this service correct?

You’re storing your access token in the iCloud KeyChain correct? I’m no security expert either, but it’s a lot better than me rolling my own. Plus, now 1 token for all devices seems to work.

Hi, thank for your reply.

Yep, you do need to pay to use AWS, but there is a free tier of one million requests per month…

You’re absolutely right about the login flow. The “Redirect URI” that you provide when you sign up should link to the Lambda script. The code on line 76 links back to your app using [a custom URL].(Apple Developer Documentation)

As you say, the access token is stored in Keychain for security.

1 Like

@david Does this access_token expire eventually? I’m getting 403 after a couple of hours or so. It could be due to testing in different devices multiple times, but wanna be sure
Also, what happens with the access_token if user logins in another device, does the old one expires?

AFAIK, the token is once-off (never had to re-login to get a new one)
Whenever a new login is detected, a new token gets generated and that would be the token that has to be used across all your devices. The old one is discarded.

Intervals.icu only generates 1 single token for all your devices, so in order to be able to access, you need to share this token across all your devices.

On My App, I am using the user’s encrypted keychain. Most of these were discussed in just a few posts above.

1 Like