How to read User data from Google Fit API

Hello everyone, thanks in advance for any assistance that can be provided. My goal is to use OAuth2 to get users’ step data from the Google Fit API. I am able to authenticate and receive basic user info (name, email etc), but when I try to read from the Fit API, I get an error that the authentication credential is missing.

Relevant Code:

import * as Google from 'expo-google-app-auth';
...

const config = {
  androidClientId: '...',
  androidStandaloneAppClientId: '...',
  scopes: ['openid', 'profile', 'https://www.googleapis.com/auth/fitness.activity.read']
}

const { type, accessToken, user } = await Google.logInAsync(config);

let userInfoResponse = await fetch('https://www.googleapis.com/userinfo/v2/me', {
  headers: { Authorization: `Bearer ${accessToken}` },
});

const resp = await userInfoResponse.json(); // this works and returns user info

const today = new Date().getTime();
const past = today - (5 * 24 * 60 * 60 * 100);
    
const url = 'https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate';
const body = {
  "aggregateBy": [{
    "dataTypeName": "com.google.step_count.delta",
    "dataSourceId": "derived:com.google.step_count.delta:com.google.android.gms:estimated_steps"
  }],
  "bucketByTime": { "durationMillis": 86400000 },
  "startTimeMillis": today,
  "endTimeMillis": past
}

const header = {
  'Content-Type': 'application/json; charset=utf-8',
  'Authorization': `BEARER ${accessToken}`
}

const fitness = await fetch(url, {
  method: "POST",
  headers: header,
  body: JSON.stringify({
    "aggregateBy": [{
      "dataTypeName": "com.google.step_count.delta",
      "dataSourceId": "derived:com.google.step_count.delta:com.google.android.gms:estimated_steps"
    }],
    "bucketByTime": { "durationMillis": 86400000 },
    "startTimeMillis": today,
    "endTimeMillis": past
  })
});

const fitnessResponse = await fitness.json();
// this returns:

/*
Object {
  "error": Object {
    "code": 401,
    "errors": Array [
      Object {
        "domain": "global",
        "location": "Authorization",
        "locationType": "header",
        "message": "Login Required.",
        "reason": "required",
      },
    ],
    "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "status": "UNAUTHENTICATED",
  },
}
*/

I am able to produce this issue on both the Expo client and using a built apk on a real device. For the standalone build, I am using an OAuth2 clientId from Google Console as androidStandaloneAppClientId in the config, and the Fitness API is enabled.

Does anyone know what I might be doing incorrectly?

1 Like