Currently, I am working/integrating Fitbit API on my Yii2 framework.
Code sample like this:
if($_SERVER['HTTP_HOST'] == 'localhost'){
define('REDIRECT_URI', 'https://localhost/yii/contest/FitbitDeviceChange');
}else{
define('REDIRECT_URI', "https://".$_SERVER['HTTP_HOST']."/site/SocialSiteFitfit");
}
define('HOST', 'https://api.fitbit.com/');
define('ACCESS_TOKEN_URL', 'https://api.fitbit.com/oauth2/token');
define('AUTHENTICATE_URL', 'https://www.fitbit.com/oauth2/authorize');
class FitbitApiController extends FrontController {
private $accessToken = null;
private $refreshToken = null;
private $expires = 31536000;
public $CLIENT_ID = '';
public $CLIENT_SECRET = '';
public $REDIRECT_URI = REDIRECT_URI;
/**
* fn getAuthorizationCode() launch the authorization page
*
*/
public static function getAuthorizationCode($CLIENT_ID) {
$url = AUTHENTICATE_URL.'?response_type=code&prompt=login consent&client_id='.$CLIENT_ID.
'&redirect_uri='.urlencode(REDIRECT_URI).
'&scope=activity%20profile&expires_in=31536000';
header('Location: '.$url);
}
}
API Integration is currently done and working fine, but after a certain time token expired, I never want customers again and again to accept a request, I want customers to accept requests once and never expired token and not need to connect again and again.
Any Idea how to prevent token expiration?
My refresh code URL is: https://github.com/namelivia/fitbit-http-php
Advertisement
Answer
You can use URL ‘https://api.fitbit.com/oauth2/revoke’ and your existing access_token for refresh or regenerate.
public function revoke(AccessToken $accessToken)
{
$options = $this->getOptionProvider()
->getAccessTokenOptions(self::METHOD_POST, []);
$uri = $this->appendQuery(
'https://api.fitbit.com/oauth2/revoke/oauth2/revoke',
$this->buildQueryString(['token' => $accessToken->getToken()])
);
$request = $this->getRequest(self::METHOD_POST, $uri, $options);
return $this->getResponse($request);
}
Full Example are:
<?php
namespace djchenOAuth2ClientProvider;
use LeagueOAuth2ClientProviderAbstractProvider;
use LeagueOAuth2ClientProviderExceptionIdentityProviderException;
use LeagueOAuth2ClientTokenAccessToken;
use LeagueOAuth2ClientToolBearerAuthorizationTrait;
use PsrHttpMessageResponseInterface;
class Fitbit extends AbstractProvider
{
use BearerAuthorizationTrait;
/**
* Fitbit URL.
*
* @const string
*/
const BASE_FITBIT_URL = 'https://www.fitbit.com';
/**
* Fitbit API URL.
*
* @const string
*/
const BASE_FITBIT_API_URL = 'https://api.fitbit.com';
/**
* HTTP header Accept-Language.
*
* @const string
*/
const HEADER_ACCEPT_LANG = 'Accept-Language';
/**
* HTTP header Accept-Locale.
*
* @const string
*/
const HEADER_ACCEPT_LOCALE = 'Accept-Locale';
/**
* Overridden to inject our options provider
* @param array $options
* @param array $collaborators
*/
public function __construct(array $options = [], array $collaborators = [])
{
$collaborators['optionProvider'] = new FitbitOptionsProvider(
$options['clientId'],
$options['clientSecret']
);
parent::__construct($options, $collaborators);
}
/**
* Get authorization url to begin OAuth flow.
*
* @return string
*/
public function getBaseAuthorizationUrl()
{
return static::BASE_FITBIT_URL.'/oauth2/authorize';
}
/**
* Get access token url to retrieve token.
*
* @param array $params
*
* @return string
*/
public function getBaseAccessTokenUrl(array $params)
{
return static::BASE_FITBIT_API_URL.'/oauth2/token';
}
/**
* Returns the url to retrieve the resource owners's profile/details.
*
* @param AccessToken $token
*
* @return string
*/
public function getResourceOwnerDetailsUrl(AccessToken $token)
{
return static::BASE_FITBIT_API_URL.'/1/user/-/profile.json';
}
/**
* Returns all scopes available from Fitbit.
* It is recommended you only request the scopes you need!
*
* @return array
*/
protected function getDefaultScopes()
{
return ['activity', 'heartrate', 'location', 'profile', 'settings', 'sleep', 'social', 'weight', 'nutrition'];
}
/**
* Checks Fitbit API response for errors.
*
* @throws IdentityProviderException
*
* @param ResponseInterface $response
* @param array|string $data Parsed response data
*/
protected function checkResponse(ResponseInterface $response, $data)
{
if ($response->getStatusCode() >= 400) {
$errorMessage = '';
if (!empty($data['errors'])) {
foreach ($data['errors'] as $error) {
if (!empty($errorMessage)) {
$errorMessage .= ' , ';
}
$errorMessage .= implode(' - ', $error);
}
} else {
$errorMessage = $response->getReasonPhrase();
}
throw new IdentityProviderException(
$errorMessage,
$response->getStatusCode(),
$response
);
}
}
/**
* Returns the string used to separate scopes.
*
* @return string
*/
protected function getScopeSeparator()
{
return ' ';
}
/**
* Returns authorization parameters based on provided options.
* Fitbit does not use the 'approval_prompt' param and here we remove it.
*
* @param array $options
*
* @return array Authorization parameters
*/
protected function getAuthorizationParameters(array $options)
{
$params = parent::getAuthorizationParameters($options);
unset($params['approval_prompt']);
if (!empty($options['prompt'])) {
$params['prompt'] = $options['prompt'];
}
return $params;
}
/**
* Generates a resource owner object from a successful resource owner
* details request.
*
* @param array $response
* @param AccessToken $token
*
* @return FitbitUser
*/
public function createResourceOwner(array $response, AccessToken $token)
{
return new FitbitUser($response);
}
/**
* Returns the key used in the access token response to identify the resource owner.
*
* @return string|null Resource owner identifier key
*/
protected function getAccessTokenResourceOwnerId()
{
return 'user_id';
}
/**
* Revoke access for the given token.
*
* @param AccessToken $accessToken
*
* @return mixed
*/
public function revoke(AccessToken $accessToken)
{
$options = $this->getOptionProvider()
->getAccessTokenOptions(self::METHOD_POST, []);
$uri = $this->appendQuery(
self::BASE_FITBIT_API_URL.'/oauth2/revoke',
$this->buildQueryString(['token' => $accessToken->getToken()])
);
$request = $this->getRequest(self::METHOD_POST, $uri, $options);
return $this->getResponse($request);
}
public function parseResponse(ResponseInterface $response)
{
return parent::parseResponse($response);
}
/**
* Parse Fitbit API Rate Limit headers and return a FitbitRateLimit object.
*
* @param ResponseInterface $response
*
* @return FitbitRateLimit Fitbit API Rate Limit information
*/
public function getFitbitRateLimit(ResponseInterface $response)
{
return new FitbitRateLimit($response);
}
}
You should read fitbit auth2 document also for more details about parameters: https://dev.fitbit.com/build/reference/web-api/oauth2/
and check full code : https://github.com/djchen/oauth2-fitbit/tree/master/src/Provider