"INVALID" Service Account key on Google Cloud Platform - authentication

I use the GCP Text-to-Speech API to create greetings and interactive menus that are played to phone customers who call into businesses. I have successfully used the Text-to-Speech API in the past using this Google quick-start: Google Cloud Text-to-Speech
I used the same quick-start guide again for a new organization and project but I keep getting an invalid key error which I have been unable to debug.
Here are the commands I have used to invoke the service and the results:
# curl -X POST \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)”\
-H "Content-Type: application/json; charset=utf-8" \
-d #request.json \
https://texttospeech.googleapis.com/v1/text:synthesize > synthesize-output-base64.txt
{
"error": {
"code": 403,
"message": "The request is missing a valid API key.",
"status": "PERMISSION_DENIED"
}
}
I tried again with a different authentication header:
# curl -X POST \
-H "X-Goog-Api-Key:***my_API_key***.json" \
-H "Content-Type: application/json; charset=utf-8" \
-d #request.json \
https://texttospeech.googleapis.com/v1/text:synthesize > synthesize-output-base64.txt
{
"error": {
"code": 400,
"message": "API key not valid. Please pass a valid API key.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "API_KEY_INVALID",
"domain": "googleapis.com",
"metadata": {
"service": "texttospeech.googleapis.com"
}
}
]
}
}
I have re-verified the following configurations:
The Text-to-Speech API is enabled for my project.
The credential (service account) I am attempting to use is listed with the Text-to-Speech API as compatible. I verified that that service account key is the key that was used in the attempted authentications.
I compared my configuration on GCP with another working configuration I manage for a different company. There are no differences I can see.
I compared my key and the other company's working key and they are identical except for the specific user data.
The billing account for the project is active with valid payment card in place.
These two links were helpful but did not clear up the problem:
Google Cloud Text-to-Speech API - permission error
Google Cloud Text to Speech INVALID API KEY
Any help on this issue would be very appreciated!

The solution to this problem is to install the Google Cloud SDK.
The CLI was missing so the returned output from gcloud auth application-default print-access-token was an error.

I enabled the Cloud Text-to-Speech API
I created a service account with Editor role.
Note: Ensure you have set the GOOGLE_APPLICATION_CREDENTIALS environment variable to your service account private key file path.
Save the request body in a file called request.json,
Execute the following command:
curl -X POST \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
-H "Content-Type: application/json; charset=utf-8" \
-d #request.json \
https://texttospeech.googleapis.com/v1/text:synthesize
Response body
{
"audioContent": "//NExAARcrn0ABhEudAgAjuem7vohckY3IAFgWvxrBkAD//ARvqc/QhCZ/6EJO6E9Dvo2cjHPQhLfWQ/rTU7yEznsoGBn8hJz5xbQiOgEfwDzD1DVARLPlzGNXylbM8s//NExA0SCnoAAUIQAd8vlrM9DPR//6t5fpUpS
sk3MbzGUvMhqOpdSsjmcpeY2Zz ...................
}
Everything worked as expected

Related

GCP API Gateway with an API Key fails with 403 error stating ... .cloud.goog is not enabled for the project

First things first, let me show you some of my gcloud settings. When I run gcloud config list, this is my output:
[core]
account = <SERVICE ACCOUNT NAME>#<PROJECT NAME>.iam.gserviceaccount.com
disable_usage_reporting = True
project = <PROJECT NAME>
Your active configuration is: [default]
When I run gcloud services list, this is my output:
apigateway.googleapis.com API Gateway API
artifactregistry.googleapis.com Artifact Registry API
bigquery.googleapis.com BigQuery API
bigquerymigration.googleapis.com BigQuery Migration API
bigquerystorage.googleapis.com BigQuery Storage API
cloudapis.googleapis.com Google Cloud APIs
cloudbuild.googleapis.com Cloud Build API
clouddebugger.googleapis.com Cloud Debugger API
cloudfunctions.googleapis.com Cloud Functions API
cloudresourcemanager.googleapis.com Cloud Resource Manager API
cloudtrace.googleapis.com Cloud Trace API
containerregistry.googleapis.com Container Registry API
datastore.googleapis.com Cloud Datastore API
eventarc.googleapis.com Eventarc API
iam.googleapis.com Identity and Access Management (IAM) API
iamcredentials.googleapis.com IAM Service Account Credentials API
logging.googleapis.com Cloud Logging API
monitoring.googleapis.com Cloud Monitoring API
oslogin.googleapis.com Cloud OS Login API
pubsub.googleapis.com Cloud Pub/Sub API
run.googleapis.com Cloud Run Admin API
secretmanager.googleapis.com Secret Manager API
servicecontrol.googleapis.com Service Control API
servicemanagement.googleapis.com Service Management API
serviceusage.googleapis.com Service Usage API
source.googleapis.com Legacy Cloud Source Repositories API
sql-component.googleapis.com Cloud SQL
storage-api.googleapis.com Google Cloud Storage JSON API
storage-component.googleapis.com Cloud Storage
storage.googleapis.com Cloud Storage API
sts.googleapis.com Security Token Service API
I have an API Gateway with the following config file:
swagger: '2.0'
info:
title: <API TITLE>
description: API Gateway First for Sphrn Testing
version: 1.0.0
securityDefinitions:
api_key_header:
type: apiKey
name: x-api-key
in: header
schemes:
- https
produces:
- application/json
paths:
/entrypoint1:
post:
summary: Simple echo service
operationId: <OPERATION ID HERE>
x-google-backend:
address: https://<CLOUD FUNCTION NAME>-<STRING I DON'T RECOGNIZE>-uc.a.run.app
security:
- api_key_header: []
responses:
'200':
description: OK
I call the api from my command line with this script:
curl --location --request POST 'https://<API CALLABLE ENDPOINT>.uc.gateway.dev/endpoint1' \
--header 'X-goog-api-key: <MY API KEY HERE>' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"name": "Test1"
}'
but it fails with this in my terminal:
{"code":403,"message":"PERMISSION_DENIED:API <SERVICE ACCOUNT NAME>-<STRING I DON'T RECOGNIZE>.apigateway.<PROJECT NAME>.cloud.goog is not enabled for the project."}
My API key looks like this:
And I went into the logs explorer for the API Gateway endpoint and this is the more detailed logs from my 403 failed curl command (sanitized for identifying information of course):
{
"httpRequest": {
"latency": "0.040s",
"protocol": "http",
"remoteIp": "<MY IP ADDRESS>",
"requestMethod": "POST",
"requestSize": "1053",
"requestUrl": "/endpoint1",
"responseSize": "346",
"status": 403
},
"insertId": "<LONG GUID LOOKING STRING>#a1",
"jsonPayload": {
"api_key": "<MY API KEY>",
"api_key_state": "NOT ENABLED",
"api_method": "1.<API ID>_<STRING I DON'T RECOGNIZE>_apigateway_<PROJECT NAME>_cloud_goog.<OPERATIONID FROM CONFIG YAML>",
"api_name": "1.<API ID>_<STRING I DON'T RECOGNIZE>_apigateway_<PROJECT NAME>_cloud_goog",
"api_version": "1.0.0",
"error_cause": "API <API ID>_<STRING I DON'T RECOGNIZE>.apigateway.<PROJECT NAME>.cloud.goog is not enabled for the project.",
"http_status_code": 403,
"location": "us-central1",
"log_message": "1.<API ID>_<STRING 1 I DON'T RECOGNIZE>_apigateway_<PROJECT NAME>_cloud_goog.<OPERATIONID FROM CONFIG YAML> is called",
"producer_project_id": "<PROJECT NAME>",
"response_code_detail": "service_control_check_error{SERVICE_NOT_ACTIVATED}",
"service_agent": "ESPv2/2.40.0",
"service_config_id": "<CONFIGURATION ID>",
"timestamp": "<TIMESTAMP HERE AS DECIMAL>"
},
"logName": "projects/<PROJECT NAME>/logs/<API ID>_<STRING I DON'T RECOGNIZE>.apigateway.<PROJECT NAME>.cloud.goog%2Fendpoints_log",
"receiveTimestamp": "<TIMESTAMP HERE AS STRING>",
"resource": {
"labels": {
"location": "us-central1",
"method": "1.<API ID>-<STRING I DON'T RECOGNIZE>_apigateway_<PROJECT NAME>_cloud_goog.<OPERATIONID FROM CONFIG YAML>",
"project_id": "<PROJECT NAME>",
"service": "<API ID>-<STRING I DON'T RECOGNIZE>.apigateway.<PROJECT NAME>.cloud.goog",
"version": "1.0.0"
},
"type": "api"
},
"severity": "ERROR",
"timestamp": "<TIMESTAMP HERE AS STRING>"
}
So how do I get this curl to succeed...? I'm assuming it's a permissions issue, but what permission does my service account not have?
When I run:
gcloud projects get-iam-policy <PROJECT ID> \
--flatten="bindings[].members" \
--format='table(bindings.role)' \
--filter="bindings.members:<SERVICE ACCOUNT NAME>#<PROJECT NAME>.iam.gserviceaccount.com"
I get this output:
ROLE
roles/cloudfunctions.serviceAgent
roles/serviceusage.serviceUsageViewer
I had to enable the service by using my actual "master" Gmail account with which I created the GCP project and enabling the service <SERVICE ACCOUNT NAME>-....apigateway.<PROJECT NAME>.cloud.goog via gcloud commands. Then I had 1 more problem where I didn't enable the operationId listed in my openapi config yaml file in the API key restrictions menu.
I'm assuming anyone reading this has already logged in with their service account via gcloud auth login and activated their relevant service account with gcloud auth activate-service-account <SERVICE ACCOUNT NAME>#<PROJECT NAME>.iam.gserviceaccount.com --key-file=/path/to/keyfile.json
Enable Service Fix
I switched my gcloud account to my "master" account with gcloud config set account <MASTER GCLOUD ACCOUNT NAME>#gmail.com, then:
gcloud services enable <SERVICE ACCOUNT NAME>-....apigateway.<PROJECT NAME>.cloud.goog \
--project=<PROJECT ID (THE NUMBER NOT THE TEXT NAME>
This made it so calling the API with my API key in the header give me a new error {"message":"PERMISSION_DENIED: The API targeted by this request is invalid for the given API key.","code":403}
operationId API Restriction Menu Fix
I had to enable the operationId listed in my openapi config yaml file in the API key restrictions menu. After that it appeared in the "Selected APIs" section of the API Key Credentials page:
After making this change, my curl request:
curl --location --request POST 'https://<API CALLABLE ENDPOINT>.uc.gateway.dev/endpoint1' \
--header 'X-goog-api-key: <MY API KEY HERE>' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"name": "Test1"
}'
worked perfectly!

Getting 403 Forbidden Error While Accessing Google Chrome Web Store API

We have a chrome extension in Google web store under my Google user id and I want to give API access to my colleagues (in the same organization). I am following this guide but it is not allowing me to access API. Here is exactly what I did
Created a Google Cloud console project using the email id that is
used to access the chrome store
Enabled Google Chrome Web Store API
Generated Oauth credentials as described in the link
Added my colleagues email address as test users under Oauth Consent section
Generated the "code" as described in the link using Colleague's Google ID
Successfully got the token by sending the curl request as described in the instructions above
Sent a curl API GET request using the token as shown below
curl \
-H "Authorization: $TOKEN" \
-H "x-goog-api-version: 2" \
-H "Content-Length: 0" \
-H "Expect:" \
-X GET \
-v \
https://www.googleapis.com/chromewebstore/v1.1/items/ITEM_ID?projection=DRAFT
The response I get is this
{
"error": {
"code": 403,
"message": "Forbidden",
"errors": [
{
"message": "Forbidden",
"domain": "global",
"reason": "forbidden"
}
]
}
}
Any idea on what I am missing here?
https://www.googleapis.com/chromewebstore/v1.1/items/ITEM_ID?projection=DRAFT
The Authorization header is missing the token type: Bearer
-H "Authorization: Bearer $TOKEN"

Cloudflare Stream API Webhooks Not Working

I'm having trouble setting a Webhook URL for the Cloudflare Stream product. I am receiving an 10012 error when attempting to access the API endpoint.
I'm following the documentation located here: https://developers.cloudflare.com/stream/webhooks/
Here's the example cURL call I make:
curl -X "PUT" "https://api.cloudflare.com/client/v4/accounts/{MY_ACCOUNT}/media/webhook" \
-H 'X-Auth-Key: {MY_AUTH_KEY}' \
-H 'X-Auth-Email: {MY_EMAIL}' \
-d "{\"notification_url\":\"{A_URL}\"}"
The response received is:
{
"result": null,
"success": false,
"errors": [
{
"code": 10012,
"message": "Forbidden"
}
],
"messages": null
}
I'm confident that I am entering the correct authentication key, account ID, etc. It's all copy/pasted from dash.cloudflare.com and have verified that this API key works on other API endpoints.
I submitted a ticket and they replied after they “made some internal configuration changes” and now the webhook API endpoints work flawlessly. Thanks for the quick help, Cloudflare!

Google Sheet Update Api : Getting error [Request is missing required authentication credential]

I am calling Google Sheet Update Request in Postman with following parameters:
Url:https://sheets.googleapis.com/v4/spreadsheets/SpreadSheetId/values/SheetName!A1:D5
Request Type : PUT
Headers : Authorization - MyAccessToken
Request Body :
Getting Response :
Note : For Updating into Spreadsheet, I follow these steps :
Create an application on Google Api Console using this link and then move to Credentials section. Click Create Credentials, then OAuth Client ID, Create Application type as Web Application. For now leave the Restrictions Section. Then Create. Now Application is created.
Add some project Name in the OAuth Consent Screen Tab
Now, Authorize the API using this link. In the right corner, open the Settings Icon. Select Use your own OAuth Credentials as true. Add the Client Id and Client secret from the Project on Google Api Console. Select the Scope as https://www.googleapis.com/auth/spreadsheets under the Google Sheet Api v4 in the dropdown, then Authorize the API.
If Get redirect_mismatch_uri. then Copy the redirect URI till the oathPlayground or before the prompt parameter and paste it into the Authorized Redirect URI under the restrictions Section of project in Google Api Console. Then Access Token will be generated,
Get Access Token. Copy this access token in the request which I defined earlier.
But Getting error. I am not able to figure out the problem.
Thanks in Advance..
Since you already have a refresh token, you can retrieve access token using refresh token. As a sample, it shows a method of how to retrieve access token using refresh token by curl. The access token retrieved by refresh token has the expiration time. Please confirm it.
You can see the detail infomation here. https://developers.google.com/identity/protocols/OAuth2WebServer
Curl command :
curl -L \
--data "refresh_token=### refresh token ###" \
--data "client_id=### client id ###" \
--data "client_secret=### client secret ###" \
--data "grant_type=refresh_token" \
https://www.googleapis.com/oauth2/v4/token
Result :
{
"access_token": "### access token ###",
"token_type": "Bearer",
"expires_in": 3600
}
Below curl command is for retrieving the information of access token. If the expiration time of access token had been over, the response is {"error_description": "Invalid Value"}. If it's not, you can see a following response.
Retrieve information of access token :
curl -L \
--data "access_token=### access token ###" \
https://www.googleapis.com/oauth2/v2/tokeninfo
Result :
{
"issued_to": "#####",
"audience": "#####",
"scope": "#####",
"expires_in": 1234,
"access_type": "offline"
}
EDIT1
This sample code is for updating the range of sheet1!A1:C2 to [["test1","test2","test3"],["test4","test5","test6"]].
Sample code :
curl -L -X PUT \
-H "Authorization: Bearer ### access token ###" \
-H "Content-Type: application/json" \
-d '{"values":[["test1","test2","test3"],["test4","test5","test6"]]}' \
"https://sheets.googleapis.com/v4/spreadsheets/### spreadsheet ID ###/values/sheet1%21a1%3ac2?valueInputOption=USER_ENTERED"
Result :
{
"spreadsheetId": "### spreadsheet ID ###",
"updatedRange": "sheet1!A1:C2",
"updatedRows": 2,
"updatedColumns": 3,
"updatedCells": 6
}

`Required session does not exist` error while using REST api of Quickblox

I am using REST api of Quickblox. but everytime , i am getting response :
{"errors": {
"base": ["Required session does not exist"]
}}
And i am using below api : url : http://api.quickblox.com/users.json
Data & header is :
curl -X POST \
-H "Content-Type: application/json" \
-H "QuickBlox-REST-API-Version: 0.1.0" \
-H "QB-Token: cf5709d6013fdb7a6787fbeb8340afed8aec4c69" \
-d '{"user": {"login": "xyz", "password": "xyz#123", "email": "xyz#domain.com", "external_user_id": "68764641", "facebook_id": "87964654", "twitter_id": "132132", "full_name": "test 1234", "phone": "87654351", "website": "", "tag_list": ""}}' \
can anybody help me to resolve this error?
When someone connects with an app using QuickBlox, the app has to obtain an access token which provides temporary, secure access to QuickBlox APIs.
A session token is an opaque string that identifies a user and an app.
Session tokens are obtained via Create Session request.
Then, because of privacy checks, all REST API requests must be authenticated with a token - the QB-Token header of each request to REST API must contain valid session token.
Expiration time for session token is 2 hours after last request to REST API. Be aware about it. If you will perform query with expired token - you will receive error 'Required session does not exist'. In this case you have to recreate a session token.
Each REST API response contains header 'QB-Token-ExpirationDate' which contains session token expiration date.