2 * Copyright (c) 2010-2023 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.wwn.rest;
15 import java.io.IOException;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.openhab.binding.nest.internal.wwn.WWNBindingConstants;
19 import org.openhab.binding.nest.internal.wwn.WWNUtils;
20 import org.openhab.binding.nest.internal.wwn.config.WWNAccountConfiguration;
21 import org.openhab.binding.nest.internal.wwn.dto.WWNAccessTokenData;
22 import org.openhab.binding.nest.internal.wwn.exceptions.InvalidWWNAccessTokenException;
23 import org.openhab.core.io.net.http.HttpUtil;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * Retrieves the WWN 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 WWNAuthorizer {
35 private final Logger logger = LoggerFactory.getLogger(WWNAuthorizer.class);
37 private final WWNAccountConfiguration 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 WWNAuthorizer(WWNAccountConfiguration config) {
50 * Get the current access token, refreshing if needed.
52 * @throws InvalidWWNAccessTokenException thrown when the access token is invalid and could not be refreshed
54 public String getNewAccessToken() throws InvalidWWNAccessTokenException {
56 String pincode = config.pincode;
57 if (pincode == null || pincode.isBlank()) {
58 throw new InvalidWWNAccessTokenException("Pincode is empty");
61 StringBuilder urlBuilder = new StringBuilder(WWNBindingConstants.NEST_ACCESS_TOKEN_URL) //
62 .append("?client_id=") //
63 .append(config.productId) //
64 .append("&client_secret=") //
65 .append(config.productSecret) //
68 .append("&grant_type=authorization_code");
70 logger.debug("Requesting access token from URL: {}", urlBuilder);
72 String responseContentAsString = HttpUtil.executeUrl("POST", urlBuilder.toString(), null, null,
73 "application/x-www-form-urlencoded", 10_000);
75 WWNAccessTokenData data = WWNUtils.fromJson(responseContentAsString, WWNAccessTokenData.class);
76 logger.debug("Received: {}", data);
78 String accessToken = data.getAccessToken();
79 if (accessToken == null || accessToken.isBlank()) {
80 throw new InvalidWWNAccessTokenException("Pincode to obtain access token is already used or invalid)");
83 } catch (IOException e) {
84 throw new InvalidWWNAccessTokenException("Access token request failed", e);