Replace deprecated Google OAuth OOB flow (#12602)

This replaces the deprecated OOB OAuth flow used in the Nest Binding and Google TTS add-ons.

Instead they will now use https://www.google.com as redirect_uri.
The instructions in the README and config descriptions have been updated for this change.

See: https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html#disallowed-oob

Fixes #12455

Signed-off-by: Wouter Born <github@maindrain.net>
This commit is contained in:
Wouter Born 2022-04-12 22:39:10 +02:00
parent 765b98c203
commit 68f9c13719
No known key found for this signature in database
GPG Key ID: A58E5C231E0E72B5
9 changed files with 38 additions and 34 deletions

View File

@ -67,8 +67,9 @@ Now an OAuth 2.0 client is created and configured for using the SDM API by the b
1. Create a new client on the "Credentials" page ([APIs & Services > Credentials](https://console.cloud.google.com/apis/credentials)): 1. Create a new client on the "Credentials" page ([APIs & Services > Credentials](https://console.cloud.google.com/apis/credentials)):
1. Click the "Create Credentials" button at the top of the page 1. Click the "Create Credentials" button at the top of the page
1. Choose "OAuth client ID" 1. Choose "OAuth client ID"
1. As "Application type" choose "TVs and Limited Input devices" 1. As "Application type" choose "Web application"
1. Give it a name so you can remember what it is used for (e.g. `Nest Binding SDM`) 1. Give it a name so you can remember what it is used for (e.g. `Nest Binding SDM`)
1. Add "https://www.google.com" to the "Authorized redirect URIs"
1. Click "Create" to create the client 1. Click "Create" to create the client
1. Copy and save the generated **Client ID** (e.g. `1046297811237-3f5sj4ccfubit0fum027ral82jgffsd1.apps.googleusercontent.com`) and **Client Secret** (e.g. `726kcU-d1W4RXxEJA79oZ0oG`) somewhere 1. Copy and save the generated **Client ID** (e.g. `1046297811237-3f5sj4ccfubit0fum027ral82jgffsd1.apps.googleusercontent.com`) and **Client Secret** (e.g. `726kcU-d1W4RXxEJA79oZ0oG`) somewhere
1. Configure the SDM project to use the created client: 1. Configure the SDM project to use the created client:
@ -88,19 +89,19 @@ Finally, an SDM Account Thing can be created to access the SDM project using the
1. Create an authorization code for the binding: 1. Create an authorization code for the binding:
1. Replace the **Project ID** and **Client ID** in the URL below with your SDM Project ID and SDM OAuth 2.0 Client ID and open the URL in a new browser tab: 1. Replace the **Project ID** and **Client ID** in the URL below with your SDM Project ID and SDM OAuth 2.0 Client ID and open the URL in a new browser tab:
`https://nestservices.google.com/partnerconnections/<ProjectID>/auth?redirect_uri=urn:ietf:wg:oauth:2.0:oob&access_type=offline&prompt=consent&client_id=<ClientID>&response_type=code&scope=https://www.googleapis.com/auth/sdm.service` `https://nestservices.google.com/partnerconnections/<ProjectID>/auth?scope=https://www.googleapis.com/auth/sdm.service&access_type=offline&include_granted_scopes=true&response_type=code&redirect_uri=https://www.google.com&client_id=<ClientID>`
For the example values used so far this is: For the example values used so far this is:
`https://nestservices.google.com/partnerconnections/585de72e-968c-435c-b16a-31d1d3f76833/auth?redirect_uri=urn:ietf:wg:oauth:2.0:oob&access_type=offline&prompt=consent&client_id=1046297811237-3f5sj4ccfubit0fum027ral82jgffsd1.apps.googleusercontent.com&response_type=code&scope=https://www.googleapis.com/auth/sdm.service` `https://nestservices.google.com/partnerconnections/585de72e-968c-435c-b16a-31d1d3f76833/auth?scope=https://www.googleapis.com/auth/sdm.service&access_type=offline&include_granted_scopes=true&response_type=code&redirect_uri=https://www.google.com&client_id=1046297811237-3f5sj4ccfubit0fum027ral82jgffsd1.apps.googleusercontent.com`
1. Enable all the permissions you want to use with the binding and click "Next" to continue 1. Enable all the permissions you want to use with the binding and click "Next" to continue
1. Login using your Google account when prompted 1. Login using your Google account when prompted
1. On the "Google hasn't verified this app" page, click on "Advanced" 1. On the "Google hasn't verified this app" page, click on "Advanced"
1. Then click on "Go to ... (advanced)" 1. Then click on "Go to ... (advanced)"
1. Now "Allow" the SDM permissions and confirm your choices again by clicking "Allow" 1. Now "Allow" the SDM permissions and confirm your choices again by clicking "Allow"
1. Next the "Sign in" page will show the **Authorization Code** 1. After your browser has been redirected to https://www.google.com, the **Authorization Code** will be set in the browser URL as value of the "code" URL query parameter
1. Copy/paste the **Authorization Code** to the SDM group parameter in the openHAB Nest SDM Account Thing configuration 1. Copy/paste the **Authorization Code** to the SDM group parameter in the openHAB Nest SDM Account Thing configuration
1. All required SDM Account Thing configuration parameters have now been entered so create it by clicking "Create Thing". 1. All required SDM Account Thing configuration parameters have now been entered so create it by clicking "Create Thing"
The SDM Account Thing should now be ONLINE and have as status description "Using periodic refresh". The SDM Account Thing should now be ONLINE and have as status description "Using periodic refresh".
It should also be possible to use the configured account to discover your Nest devices via the Inbox. It should also be possible to use the configured account to discover your Nest devices via the Inbox.
@ -134,8 +135,9 @@ Next an OAuth 2.0 client is created which is used to create a Pub/Sub subscripti
1. Open the "Credentials" page ([APIs & Services > Credentials](https://console.cloud.google.com/apis/credentials)): 1. Open the "Credentials" page ([APIs & Services > Credentials](https://console.cloud.google.com/apis/credentials)):
1. Click the "Create Credentials" button at the top of the page 1. Click the "Create Credentials" button at the top of the page
1. Choose "OAuth client ID" 1. Choose "OAuth client ID"
1. As "Application type" choose "TVs and Limited Input devices" 1. As "Application type" choose "Web application"
1. Give it a name so you can remember what it is used for (e.g. `Nest Binding Pub/Sub`) 1. Give it a name so you can remember what it is used for (e.g. `Nest Binding Pub/Sub`)
1. Add "https://www.google.com" to the "Authorized redirect URIs"
1. Click "Create" to create the client 1. Click "Create" to create the client
1. Copy and save the generated **Client ID** (e.g. `1046297811237-lg27h26kln6r1nbg54jpg6nfjg6h4b3n.apps.googleusercontent.com`) and **Client Secret** (e.g. `1-k78-XcHhp_gdZF-I6JaIHp`) somewhere 1. Copy and save the generated **Client ID** (e.g. `1046297811237-lg27h26kln6r1nbg54jpg6nfjg6h4b3n.apps.googleusercontent.com`) and **Client Secret** (e.g. `1-k78-XcHhp_gdZF-I6JaIHp`) somewhere
@ -151,18 +153,18 @@ Finally, the existing SDM Account Thing can be updated so it can subscribe to SD
1. Create an authorization code for the binding: 1. Create an authorization code for the binding:
1. Replace the **Client ID** in the URL below with your Pub/Sub OAuth 2.0 Client ID and open the URL in a new browser tab: 1. Replace the **Client ID** in the URL below with your Pub/Sub OAuth 2.0 Client ID and open the URL in a new browser tab:
`https://accounts.google.com/o/oauth2/auth?client_id=<ClientID>&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=https://www.googleapis.com/auth/pubsub` `https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/pubsub&access_type=offline&include_granted_scopes=true&response_type=code&redirect_uri=https://www.google.com&client_id=<ClientID>`
For the example client this is: For the example client this is:
`https://accounts.google.com/o/oauth2/auth?client_id=1046297811237-lg27h26kln6r1nbg54jpg6nfjg6h4b3n.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=https://www.googleapis.com/auth/pubsub` `https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/pubsub&access_type=offline&include_granted_scopes=true&response_type=code&redirect_uri=https://www.google.com&client_id=1046297811237-lg27h26kln6r1nbg54jpg6nfjg6h4b3n.apps.googleusercontent.com`
1. Login using your Google account when prompted 1. Login using your Google account when prompted
1. On the "Google hasn't verified this app" page, click on "Advanced" 1. On the "Google hasn't verified this app" page, click on "Advanced"
1. Then click on "Go to ... (advanced)" 1. Then click on "Go to ... (advanced)"
1. Now "Allow" the Pub/Sub permissions and confirm your choices again by clicking "Allow" 1. Now "Allow" the Pub/Sub permissions and confirm your choices again by clicking "Allow"
1. Next the "Sign in" page will show the **Authorization Code** 1. After your browser has been redirected to https://www.google.com, the **Authorization Code** will be set in the browser URL as value of the "code" URL query parameter
1. Copy/paste the **Authorization Code** to the Pub/Sub group parameter in the openHAB Nest SDM Account Thing configuration 1. Copy/paste the **Authorization Code** to the Pub/Sub group parameter in the openHAB Nest SDM Account Thing configuration
1. All required Pub/Sub Account Thing configuration parameters have now been entered so click "Save" to update the SDM Account Thing configuration. 1. All required Pub/Sub Account Thing configuration parameters have now been entered so click "Save" to update the SDM Account Thing configuration
The SDM Account Thing should now be ONLINE and have as status description "Using periodic refresh and Pub/Sub". The SDM Account Thing should now be ONLINE and have as status description "Using periodic refresh and Pub/Sub".

View File

@ -86,13 +86,13 @@ public class PubSubAPI {
if (pullResponse != null && pullResponse.receivedMessages != null) { if (pullResponse != null && pullResponse.receivedMessages != null) {
logger.debug("Subscription '{}' has {} new message(s)", subscriptionId, logger.debug("Subscription '{}' has {} new message(s)", subscriptionId,
pullResponse.receivedMessages.size()); pullResponse.receivedMessages.size());
forEachListener((listener) -> pullResponse.receivedMessages forEachListener(listener -> pullResponse.receivedMessages
.forEach((message) -> listener.onMessage(message.message))); .forEach(message -> listener.onMessage(message.message)));
List<String> ackIds = pullResponse.receivedMessages.stream().map(message -> message.ackId) List<String> ackIds = pullResponse.receivedMessages.stream().map(message -> message.ackId)
.collect(Collectors.toList()); .collect(Collectors.toList());
acknowledgeSubscriptionMessages(subscriptionId, ackIds); acknowledgeSubscriptionMessages(subscriptionId, ackIds);
} else { } else {
forEachListener((listener) -> listener.onNoNewMessages()); forEachListener(PubSubSubscriptionListener::onNoNewMessages);
} }
scheduler.submit(this); scheduler.submit(this);
@ -100,15 +100,15 @@ public class PubSubAPI {
logger.debug("Expected exception while pulling message for '{}' subscription", subscriptionId, e); logger.debug("Expected exception while pulling message for '{}' subscription", subscriptionId, e);
Throwable cause = e.getCause(); Throwable cause = e.getCause();
if (!(cause instanceof InterruptedException)) { if (!(cause instanceof InterruptedException)) {
forEachListener((listener) -> listener.onError(e)); forEachListener(listener -> listener.onError(e));
scheduler.schedule(this, RETRY_TIMEOUT.toNanos(), TimeUnit.NANOSECONDS); scheduler.schedule(this, RETRY_TIMEOUT.toNanos(), TimeUnit.NANOSECONDS);
} }
} catch (InvalidPubSubAccessTokenException e) { } catch (InvalidPubSubAccessTokenException e) {
logger.warn("Cannot pull messages for '{}' subscription (access token invalid)", subscriptionId, e); logger.warn("Cannot pull messages for '{}' subscription (access token invalid)", subscriptionId, e);
forEachListener((listener) -> listener.onError(e)); forEachListener(listener -> listener.onError(e));
} catch (Exception e) { } catch (Exception e) {
logger.warn("Unexpected exception while pulling message for '{}' subscription", subscriptionId, e); logger.warn("Unexpected exception while pulling message for '{}' subscription", subscriptionId, e);
forEachListener((listener) -> listener.onError(e)); forEachListener(listener -> listener.onError(e));
scheduler.schedule(this, RETRY_TIMEOUT.toNanos(), TimeUnit.NANOSECONDS); scheduler.schedule(this, RETRY_TIMEOUT.toNanos(), TimeUnit.NANOSECONDS);
} }
} }
@ -125,7 +125,7 @@ public class PubSubAPI {
private static final String AUTH_URL = "https://accounts.google.com/o/oauth2/auth"; private static final String AUTH_URL = "https://accounts.google.com/o/oauth2/auth";
private static final String TOKEN_URL = "https://accounts.google.com/o/oauth2/token"; private static final String TOKEN_URL = "https://accounts.google.com/o/oauth2/token";
private static final String REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob"; private static final String REDIRECT_URI = "https://www.google.com";
private static final String PUBSUB_HANDLE_FORMAT = "%s.pubsub"; private static final String PUBSUB_HANDLE_FORMAT = "%s.pubsub";
private static final String PUBSUB_SCOPE = "https://www.googleapis.com/auth/pubsub"; private static final String PUBSUB_SCOPE = "https://www.googleapis.com/auth/pubsub";
@ -203,7 +203,7 @@ public class PubSubAPI {
listeners.remove(listener); listeners.remove(listener);
if (listeners.isEmpty()) { if (listeners.isEmpty()) {
subscriptionListeners.remove(subscriptionId); subscriptionListeners.remove(subscriptionId);
scheduler.getQueue().removeIf((runnable) -> runnable instanceof Subscriber scheduler.getQueue().removeIf(runnable -> runnable instanceof Subscriber
&& ((Subscriber) runnable).subscriptionId.equals(subscriptionId)); && ((Subscriber) runnable).subscriptionId.equals(subscriptionId));
} }
} }

View File

@ -68,7 +68,7 @@ public class SDMAPI {
private static final String AUTH_URL = "https://accounts.google.com/o/oauth2/auth"; private static final String AUTH_URL = "https://accounts.google.com/o/oauth2/auth";
private static final String TOKEN_URL = "https://accounts.google.com/o/oauth2/token"; private static final String TOKEN_URL = "https://accounts.google.com/o/oauth2/token";
private static final String REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob"; private static final String REDIRECT_URI = "https://www.google.com";
private static final String SDM_HANDLE_FORMAT = "%s.sdm"; private static final String SDM_HANDLE_FORMAT = "%s.sdm";
private static final String SDM_SCOPE = "https://www.googleapis.com/auth/sdm.service"; private static final String SDM_SCOPE = "https://www.googleapis.com/auth/sdm.service";
@ -163,7 +163,7 @@ public class SDMAPI {
ContentResponse contentResponse = request.send(); ContentResponse contentResponse = request.send();
logResponseErrors(contentResponse); logResponseErrors(contentResponse);
logger.debug("Retrieved camera image from: {}", url); logger.debug("Retrieved camera image from: {}", url);
requestListeners.forEach(listener -> listener.onSuccess()); requestListeners.forEach(SDMAPIRequestListener::onSuccess);
return contentResponse.getContent(); return contentResponse.getContent();
} catch (ExecutionException | InterruptedException | TimeoutException e) { } catch (ExecutionException | InterruptedException | TimeoutException e) {
logger.debug("Failed to get camera image", e); logger.debug("Failed to get camera image", e);
@ -302,7 +302,7 @@ public class SDMAPI {
logResponseErrors(contentResponse); logResponseErrors(contentResponse);
String response = contentResponse.getContentAsString(); String response = contentResponse.getContentAsString();
logger.debug("Response: {}", response); logger.debug("Response: {}", response);
requestListeners.forEach(listener -> listener.onSuccess()); requestListeners.forEach(SDMAPIRequestListener::onSuccess);
return response; return response;
} catch (ExecutionException | InterruptedException | IOException | TimeoutException e) { } catch (ExecutionException | InterruptedException | IOException | TimeoutException e) {
logger.debug("Failed to send JSON GET request", e); logger.debug("Failed to send JSON GET request", e);
@ -327,7 +327,7 @@ public class SDMAPI {
logResponseErrors(contentResponse); logResponseErrors(contentResponse);
String response = contentResponse.getContentAsString(); String response = contentResponse.getContentAsString();
logger.debug("Response: {}", response); logger.debug("Response: {}", response);
requestListeners.forEach(listener -> listener.onSuccess()); requestListeners.forEach(SDMAPIRequestListener::onSuccess);
return response; return response;
} catch (ExecutionException | InterruptedException | IOException | TimeoutException e) { } catch (ExecutionException | InterruptedException | IOException | TimeoutException e) {
logger.debug("Failed to send JSON POST request", e); logger.debug("Failed to send JSON POST request", e);

View File

@ -29,7 +29,7 @@
</parameter> </parameter>
<parameter name="sdmAuthorizationCode" type="text" groupName="sdm"> <parameter name="sdmAuthorizationCode" type="text" groupName="sdm">
<label>Authorization Code</label> <label>Authorization Code</label>
<description><![CDATA[The one time authorization code used to retrieve the refresh and access token used with the SDM API. The code is obtained by following the instructions at the following URL in your browser:<br><br>https://nestservices.google.com/partnerconnections/{{ProjectID}}/auth?redirect_uri=urn:ietf:wg:oauth:2.0:oob&access_type=offline&prompt=consent&client_id={{ClientID}}&response_type=code&scope=https://www.googleapis.com/auth/sdm.service]]></description> <description><![CDATA[The one time authorization code used to retrieve the refresh and access token used with the SDM API. The code is obtained by following the instructions at the following URL in your browser:<br><br>https://nestservices.google.com/partnerconnections/{{ProjectID}}/auth?scope=https://www.googleapis.com/auth/sdm.service&access_type=offline&include_granted_scopes=true&response_type=code&redirect_uri=https://www.google.com&client_id={{ClientID}}<br><br>After your browser has been redirected to https://www.google.com, the authorization code will be set in the browser URL as value of the "code" URL query parameter.]]></description>
</parameter> </parameter>
<parameter name="pubsubProjectId" type="text" groupName="pubsub"> <parameter name="pubsubProjectId" type="text" groupName="pubsub">
@ -51,7 +51,7 @@
</parameter> </parameter>
<parameter name="pubsubAuthorizationCode" type="text" groupName="pubsub"> <parameter name="pubsubAuthorizationCode" type="text" groupName="pubsub">
<label>Authorization Code</label> <label>Authorization Code</label>
<description><![CDATA[The one time authorization code used to retrieve the refresh and access token used with the Pub/Sub API. The code is obtained by following the instructions at the following URL in your browser:<br><br>https://accounts.google.com/o/oauth2/auth?client_id={{ClientID}}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=https://www.googleapis.com/auth/pubsub]]></description> <description><![CDATA[The one time authorization code used to retrieve the refresh and access token used with the Pub/Sub API. The code is obtained by following the instructions at the following URL in your browser:<br><br>https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/pubsub&access_type=offline&include_granted_scopes=true&response_type=code&redirect_uri=https://www.google.com&client_id={{ClientID}}<br><br>After your browser has been redirected to https://www.google.com, the authorization code will be set in the browser URL as value of the "code" URL query parameter.]]></description>
</parameter> </parameter>
</config-description> </config-description>

View File

@ -35,7 +35,7 @@ thing-type.config.nest.sdm_account.group.pubsub.description = The parameters use
thing-type.config.nest.sdm_account.group.sdm.label = SDM thing-type.config.nest.sdm_account.group.sdm.label = SDM
thing-type.config.nest.sdm_account.group.sdm.description = The parameters used when communicating with the SDM API thing-type.config.nest.sdm_account.group.sdm.description = The parameters used when communicating with the SDM API
thing-type.config.nest.sdm_account.pubsubAuthorizationCode.label = Authorization Code thing-type.config.nest.sdm_account.pubsubAuthorizationCode.label = Authorization Code
thing-type.config.nest.sdm_account.pubsubAuthorizationCode.description = The one time authorization code used to retrieve the refresh and access token used with the Pub/Sub API. The code is obtained by following the instructions at the following URL in your browser:<br><br>https://accounts.google.com/o/oauth2/auth?client_id={{ClientID}}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=https://www.googleapis.com/auth/pubsub thing-type.config.nest.sdm_account.pubsubAuthorizationCode.description = The one time authorization code used to retrieve the refresh and access token used with the Pub/Sub API. The code is obtained by following the instructions at the following URL in your browser:<br><br>https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/pubsub&access_type=offline&include_granted_scopes=true&response_type=code&redirect_uri=https://www.google.com&client_id={{ClientID}}<br><br>After your browser has been redirected to https://www.google.com, the authorization code will be set in the browser URL as value of the "code" URL query parameter.
thing-type.config.nest.sdm_account.pubsubClientId.label = Client ID thing-type.config.nest.sdm_account.pubsubClientId.label = Client ID
thing-type.config.nest.sdm_account.pubsubClientId.description = Identifies the OAuth 2.0 client used for accessing the Pub/Sub subscription thing-type.config.nest.sdm_account.pubsubClientId.description = Identifies the OAuth 2.0 client used for accessing the Pub/Sub subscription
thing-type.config.nest.sdm_account.pubsubClientSecret.label = Client Secret thing-type.config.nest.sdm_account.pubsubClientSecret.label = Client Secret
@ -45,7 +45,7 @@ thing-type.config.nest.sdm_account.pubsubProjectId.description = Identifies the
thing-type.config.nest.sdm_account.pubsubSubscriptionId.label = Subscription ID thing-type.config.nest.sdm_account.pubsubSubscriptionId.label = Subscription ID
thing-type.config.nest.sdm_account.pubsubSubscriptionId.description = Identifies the subscription that is created for subscribing to SDM Pub/Sub events thing-type.config.nest.sdm_account.pubsubSubscriptionId.description = Identifies the subscription that is created for subscribing to SDM Pub/Sub events
thing-type.config.nest.sdm_account.sdmAuthorizationCode.label = Authorization Code thing-type.config.nest.sdm_account.sdmAuthorizationCode.label = Authorization Code
thing-type.config.nest.sdm_account.sdmAuthorizationCode.description = The one time authorization code used to retrieve the refresh and access token used with the SDM API. The code is obtained by following the instructions at the following URL in your browser:<br><br>https://nestservices.google.com/partnerconnections/{{ProjectID}}/auth?redirect_uri=urn:ietf:wg:oauth:2.0:oob&access_type=offline&prompt=consent&client_id={{ClientID}}&response_type=code&scope=https://www.googleapis.com/auth/sdm.service thing-type.config.nest.sdm_account.sdmAuthorizationCode.description = The one time authorization code used to retrieve the refresh and access token used with the SDM API. The code is obtained by following the instructions at the following URL in your browser:<br><br>https://nestservices.google.com/partnerconnections/{{ProjectID}}/auth?scope=https://www.googleapis.com/auth/sdm.service&access_type=offline&include_granted_scopes=true&response_type=code&redirect_uri=https://www.google.com&client_id={{ClientID}}<br><br>After your browser has been redirected to https://www.google.com, the authorization code will be set in the browser URL as value of the "code" URL query parameter.
thing-type.config.nest.sdm_account.sdmClientId.label = Client ID thing-type.config.nest.sdm_account.sdmClientId.label = Client ID
thing-type.config.nest.sdm_account.sdmClientId.description = Identifies the OAuth 2.0 client used for accessing the SDM project thing-type.config.nest.sdm_account.sdmClientId.description = Identifies the OAuth 2.0 client used for accessing the SDM project
thing-type.config.nest.sdm_account.sdmClientSecret.label = Client Secret thing-type.config.nest.sdm_account.sdmClientSecret.label = Client Secret

View File

@ -26,8 +26,9 @@ Before you can integrate this service with your Google Cloud Text-to-Speech, you
* Enable the Cloud Text-to-Speech API. [link](https://console.cloud.google.com/apis/dashboard) * Enable the Cloud Text-to-Speech API. [link](https://console.cloud.google.com/apis/dashboard)
* Set up authentication: * Set up authentication:
* Go to the "APIs & Services" -> "Credentials" page in the GCP Console and your project. [link](https://console.cloud.google.com/apis/credentials) * Go to the "APIs & Services" -> "Credentials" page in the GCP Console and your project. [link](https://console.cloud.google.com/apis/credentials)
* From the "Create credentials" drop-down list, select "OAuth client ID. * From the "Create credentials" drop-down list, select "OAuth client ID".
* Select application type "TV and Limited Input" and enter a name into the "Name" field. * Select application type "Web application" and enter a name into the "Name" field.
* Add "https://www.google.com" to the "Authorized redirect URIs".
* Click Create. A pop-up appears, showing your "client ID" and "client secret". * Click Create. A pop-up appears, showing your "client ID" and "client secret".
## Service Configuration ## Service Configuration
@ -36,10 +37,11 @@ Using your favorite configuration UI to edit **Settings / Other Services - Googl
* **Client Id** - Google Cloud Platform OAuth 2.0-Client Id. * **Client Id** - Google Cloud Platform OAuth 2.0-Client Id.
* **Client Secret** - Google Cloud Platform OAuth 2.0-Client Secret. * **Client Secret** - Google Cloud Platform OAuth 2.0-Client Secret.
* **Authorization Code** - The auth-code is a one-time code needed to retrieve the necessary access-codes from Google Cloud Platform. * **Authorization Code** - This code is used once for retrieving the Google Cloud Platform access and refresh tokens.
**Please go to your browser ...** **Please go to your browser ...**
[https://accounts.google.com/o/oauth2/auth?client_id=<clientId>&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/cloud-platform&response_type=code](https://accounts.google.com/o/oauth2/auth?client_id=<clientId>&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/cloud-platform&response_type=code) (replace `<clientId>` by your Client Id) [https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/cloud-platform&access_type=offline&include_granted_scopes=true&response_type=code&redirect_uri=https://www.google.com&client_id=<clientId>](https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/cloud-platform&access_type=offline&include_granted_scopes=true&response_type=code&redirect_uri=https://www.google.com&client_id=<clientId>) (replace `<clientId>` by your Client Id)
**... to generate an auth-code and paste it here**. **... to generate an authorization code and paste it here**.
After your browser has been redirected to https://www.google.com, the authorization code will be set in the browser URL as value of the "code" URL query parameter.
After initial authorization, this code is not needed anymore. After initial authorization, this code is not needed anymore.
It is recommended to clear this configuration parameter afterwards. It is recommended to clear this configuration parameter afterwards.
* **Pitch** - The pitch of selected voice, up to 20 semitones. * **Pitch** - The pitch of selected voice, up to 20 semitones.

View File

@ -75,7 +75,7 @@ class GoogleCloudAPI {
private static final String GCP_AUTH_URI = "https://accounts.google.com/o/oauth2/auth"; private static final String GCP_AUTH_URI = "https://accounts.google.com/o/oauth2/auth";
private static final String GCP_TOKEN_URI = "https://accounts.google.com/o/oauth2/token"; private static final String GCP_TOKEN_URI = "https://accounts.google.com/o/oauth2/token";
private static final String GCP_REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob"; private static final String GCP_REDIRECT_URI = "https://www.google.com";
/** /**
* Google Cloud Platform authorization scope * Google Cloud Platform authorization scope
*/ */

View File

@ -26,7 +26,7 @@
</parameter> </parameter>
<parameter name="authcode" type="text" groupName="authentication"> <parameter name="authcode" type="text" groupName="authentication">
<label>Authorization Code</label> <label>Authorization Code</label>
<description><![CDATA[The auth-code is a one-time code needed to retrieve the necessary access-codes from Google Cloud Platform. <b>Please go to your browser ...</b> https://accounts.google.com/o/oauth2/auth?client_id={{clientId}}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/cloud-platform&response_type=code <b>... to generate an auth-code and paste it here</b>.]]></description> <description><![CDATA[This code is used once for retrieving the Google Cloud Platform access and refresh tokens. Open the following URL in your browser to generate an authorization code:<br><br>https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/cloud-platform&access_type=offline&include_granted_scopes=true&response_type=code&redirect_uri=https://www.google.com&client_id={{clientId}}<br><br>After your browser has been redirected to https://www.google.com, the authorization code will be set in the browser URL as value of the "code" URL query parameter.]]></description>
</parameter> </parameter>
<parameter name="pitch" type="decimal" min="-20" max="20" step="0.1" groupName="tts"> <parameter name="pitch" type="decimal" min="-20" max="20" step="0.1" groupName="tts">
<label>Pitch</label> <label>Pitch</label>

View File

@ -1,5 +1,5 @@
voice.config.googletts.authcode.label = Authorization Code voice.config.googletts.authcode.label = Authorization Code
voice.config.googletts.authcode.description = The auth-code is a one-time code needed to retrieve the necessary access-codes from Google Cloud Platform. <b>Please go to your browser ...</b> https://accounts.google.com/o/oauth2/auth?client_id={{clientId}}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/cloud-platform&response_type=code <b>... to generate an auth-code and paste it here</b>. voice.config.googletts.authcode.description = This code is used once for retrieving the Google Cloud Platform access and refresh tokens. Open the following URL in your browser to generate an authorization code:<br><br>https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/cloud-platform&access_type=offline&include_granted_scopes=true&response_type=code&redirect_uri=https://www.google.com&client_id={{clientId}}<br><br>After your browser has been redirected to https://www.google.com, the authorization code will be set in the browser URL as value of the "code" URL query parameter.
voice.config.googletts.clientId.label = Client Id voice.config.googletts.clientId.label = Client Id
voice.config.googletts.clientId.description = Google Cloud Platform OAuth 2.0-Client Id. voice.config.googletts.clientId.description = Google Cloud Platform OAuth 2.0-Client Id.
voice.config.googletts.clientSecret.label = Client Secret voice.config.googletts.clientSecret.label = Client Secret