2 * Copyright (c) 2010-2021 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.nest.internal.rest;
15 import java.io.IOException;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.openhab.binding.nest.internal.NestBindingConstants;
19 import org.openhab.binding.nest.internal.NestUtils;
20 import org.openhab.binding.nest.internal.config.NestBridgeConfiguration;
21 import org.openhab.binding.nest.internal.data.AccessTokenData;
22 import org.openhab.binding.nest.internal.exceptions.InvalidAccessTokenException;
23 import org.openhab.core.io.net.http.HttpUtil;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * Retrieves the Nest access token using the OAuth 2.0 protocol using pin-based authorization.
30 * @author David Bennett - Initial contribution
31 * @author Wouter Born - Improve exception handling
34 public class NestAuthorizer {
35 private final Logger logger = LoggerFactory.getLogger(NestAuthorizer.class);
37 private final NestBridgeConfiguration config;
40 * Create the helper class for the Nest access token. Also creates the folder
41 * to put the access token data in if it does not already exist.
43 * @param config The configuration to use for the token
45 public NestAuthorizer(NestBridgeConfiguration config) {
50 * Get the current access token, refreshing if needed.
52 * @throws InvalidAccessTokenException thrown when the access token is invalid and could not be refreshed
54 public String getNewAccessToken() throws InvalidAccessTokenException {
56 String pincode = config.pincode;
57 if (pincode == null || pincode.isBlank()) {
58 throw new InvalidAccessTokenException("Pincode is empty");
62 StringBuilder urlBuilder = new StringBuilder(NestBindingConstants.NEST_ACCESS_TOKEN_URL)
63 .append("?client_id=")
64 .append(config.productId)
65 .append("&client_secret=")
66 .append(config.productSecret)
69 .append("&grant_type=authorization_code");
72 logger.debug("Requesting access token from URL: {}", urlBuilder);
74 String responseContentAsString = HttpUtil.executeUrl("POST", urlBuilder.toString(), null, null,
75 "application/x-www-form-urlencoded", 10_000);
77 AccessTokenData data = NestUtils.fromJson(responseContentAsString, AccessTokenData.class);
78 logger.debug("Received: {}", data);
80 String accessToken = data.getAccessToken();
81 if (accessToken == null || accessToken.isBlank()) {
82 throw new InvalidAccessTokenException("Pincode to obtain access token is already used or invalid)");
85 } catch (IOException e) {
86 throw new InvalidAccessTokenException("Access token request failed", e);