Skip to content

Commit

Permalink
[ecobee] Improve handling of access token response (openhab#7506)
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Hilbush <[email protected]>
  • Loading branch information
mhilbush authored and andrewfg committed Aug 31, 2020
1 parent b331e02 commit 6f4f6dc
Showing 1 changed file with 30 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Properties;
import java.util.Set;
Expand Down Expand Up @@ -77,6 +78,7 @@ public class EcobeeApi implements AccessTokenRefreshListener {
// These errors from the API will require an Ecobee authorization
private static final int ECOBEE_TOKEN_EXPIRED = 14;
private static final int ECOBEE_DEAUTHORIZED_TOKEN = 16;
private static final int TOKEN_EXPIRES_IN_BUFFER_SECONDS = 120;

public static final Properties HTTP_HEADERS;
static {
Expand All @@ -101,7 +103,7 @@ public static Gson getGson() {
private @NonNullByDefault({}) OAuthClientService oAuthClientService;
private @NonNullByDefault({}) EcobeeAuth ecobeeAuth;

private String accessToken = "";
private @Nullable AccessTokenResponse accessTokenResponse;

public EcobeeApi(final EcobeeAccountBridgeHandler bridgeHandler, final String apiKey, final int apiTimeout,
org.eclipse.smarthome.core.auth.client.oauth2.OAuthFactory oAuthFactory, HttpClient httpClient) {
Expand Down Expand Up @@ -145,10 +147,13 @@ public void closeOAuthClientService() {
private boolean isAuthorized() {
boolean isAuthorized = false;
try {
AccessTokenResponse accessTokenResponse = oAuthClientService.getAccessTokenResponse();
if (accessTokenResponse != null) {
logger.trace("API: Got AccessTokenResponse from OAuth service: {}", accessTokenResponse);
accessToken = accessTokenResponse.getAccessToken();
AccessTokenResponse localAccessTokenResponse = oAuthClientService.getAccessTokenResponse();
if (localAccessTokenResponse != null) {
logger.trace("API: Got AccessTokenResponse from OAuth service: {}", localAccessTokenResponse);
if (localAccessTokenResponse.isExpired(LocalDateTime.now(), TOKEN_EXPIRES_IN_BUFFER_SECONDS)) {
logger.debug("API: Token is expiring soon. Refresh it now");
localAccessTokenResponse = oAuthClientService.refreshToken();
}
ecobeeAuth.setState(EcobeeAuthState.COMPLETE);
isAuthorized = true;
} else {
Expand All @@ -157,6 +162,7 @@ private boolean isAuthorized() {
ecobeeAuth.setState(EcobeeAuthState.NEED_PIN);
}
}
accessTokenResponse = localAccessTokenResponse;
ecobeeAuth.doAuthorization();
} catch (OAuthException | IOException | RuntimeException e) {
logger.info("API: Got exception trying to get access token from OAuth service", e);
Expand All @@ -173,7 +179,6 @@ private boolean isAuthorized() {

@Override
public void onAccessTokenResponse(AccessTokenResponse accessTokenResponse) {
accessToken = accessTokenResponse.getAccessToken();
}

public @Nullable SummaryResponseDTO performThermostatSummaryQuery() {
Expand Down Expand Up @@ -257,6 +262,8 @@ private String buildQueryUrl(String baseUrl, String requestJson) throws Unsuppor
logger.trace("API: Response took {} msec: {}", System.currentTimeMillis() - startTime, response);
} catch (IOException e) {
logIOException(e);
} catch (EcobeeAuthException e) {
logger.info("API: Unable to execute GET: {}", e.getMessage());
}
return response;
}
Expand All @@ -276,6 +283,8 @@ private boolean executePost(String url, String json) {
}
} catch (IOException e) {
logIOException(e);
} catch (EcobeeAuthException e) {
logger.info("API: Unable to execute POST: {}", e.getMessage());
}
return false;
}
Expand Down Expand Up @@ -306,21 +315,31 @@ private boolean isSuccess(@Nullable AbstractResponseDTO response) {
} else if (response.status.code.intValue() != 0) {
logger.info("API: Ecobee API returned unsuccessful status: code={}, message={}", response.status.code,
response.status.message);
// The following error indicate that the Ecobee PIN authorization
// process needs to be restarted
if (response.status.code == ECOBEE_TOKEN_EXPIRED || response.status.code == ECOBEE_DEAUTHORIZED_TOKEN) {
if (response.status.code == ECOBEE_DEAUTHORIZED_TOKEN) {
// Token has been deauthorized, so restart the authorization process from the beginning
logger.warn("API: Reset OAuth Client Service due to deauthorized token");
deleteOAuthClientService();
createOAuthClientService();
} else if (response.status.code == ECOBEE_TOKEN_EXPIRED) {
// Check isAuthorized again to see if we can get a valid token
logger.info("API: Unable to complete API call because token is expired");
if (!isAuthorized()) {
logger.warn("API: isAuthorized was NOT successful on second try");
}
}
success = false;
}
return success;
}

private Properties setHeaders() {
private Properties setHeaders() throws EcobeeAuthException {
AccessTokenResponse atr = accessTokenResponse;
if (atr == null) {
throw new EcobeeAuthException("Can not set auth header because access token is null");
}
Properties headers = new Properties();
headers.putAll(HTTP_HEADERS);
headers.put("Authorization", "Bearer " + accessToken);
headers.put("Authorization", "Bearer " + atr.getAccessToken());
return headers;
}
}

0 comments on commit 6f4f6dc

Please sign in to comment.