I am trying to process speech in real time in order to transcribe it, using Google Cloud's speech API.
I have a service account associated with the speech service, plus a local JSON which should authorize my requests to Google Cloud (it contains a couple of credentials). Even if the key is set to expire on January 1st, 10000, attempting to obtain the transcript generates the following error:
google.api_core.exceptions.Unauthenticated: 401 Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project. [reason: "ACCESS_TOKEN_EXPIRED"
domain: "googleapis.com"
metadata {
key: "method"
value: "google.cloud.speech.v1.Speech.StreamingRecognize"
}
metadata {
key: "service"
value: "speech.googleapis.com"
}
]
What am I doing wrong? I cannot seem to find a solution for this online.
Thank you!
Related
I want to connect to Google Analytics Reporting API to fetch data, For which I have been provided with details of the service account in JSON format which contains details like (type, project_id, client_email, client_id, private_key,client_x509_cert_url, auth_provider_x509_cert_url)
Using this JSON file I am able to connect and fetch required report data via Python code Reporting API quickstart. However, due to business requirements, I have to establish the connection using HTTP Rest API.
So based on the details of the same service account I am trying to authenticate using JWT by referring to Google Docs Addendum: Service account authorization without OAuth so that once I get the signature I can use that as a static token and make next API call to get report data https://analyticsreporting.googleapis.com/v4/reports:batchGet and passing Request Body
But while testing in https://jwt.io/ & also in https://irrte.ch/jwt-js-decode/index.html signature creation is failing with an Invalid Signature error.
Can someone please help to understand what am I missing here?
Header
{
"alg": "RS256",
"typ": "JWT",
"kid": "<service account's private key ID>"
}
Payload
{
"iss": "<service account's email address i.e. client_email>",
"sub": "<service account's email address i.e. client_email>",
"aud": "https://oauth2.googleapis.com/token",
"iat": <UTC Unix Epoch Start Time>,
"exp": <UTC Unix Epoch End Time>
}
And then pasted X.509 PUBLIC CERTIFICATE generated for the service account and in Private key pasted Private key again which is from JSON file of service account
-----BEGIN CERTIFICATE-----\nMIrrhherhehrgssreheheherhehehehrhrdsfsfzcsvsvsvscssvsrjnfvdsfsscscscshgeferttyyuuuuuuuuuuudDxE/Q\n-----END CERTIFICATE-----\n
-----BEGIN PRIVATE KEY-----\nLDSVSVSCSYUNJKOLPDFSSSFSFSFSSFSFSFSFSFSFSSFSFSFSFSFSFSFSSSSSSSSSGGGGGGGGGGGGGGGGGGGGGGUUUUUUUUUUUUUUUUUM=\n-----END PRIVATE KEY-----\n
PS: I have tried to test with \n without \n as well as with prefixes BEGIN, END and without it still have the same result.
Here's my problem:
I have a 365 Family OneDrive subscription with 3 members, my account being the admin.
I am trying to build a python application to read/extract the content of the files I have on this onedrive space based on specific criterias. I want to build it as a command line application, running locally on my PC. I am aware some tools may exist for this but I'd like to code my own solution.
After going through tons of different documentation, I ended up doing the following
Registered my application on the Azure portal
Granted some permission on the Microsoft Graph API (User.read, Files.Read and Files.ReadAll)
Created a secret
Grabbed the sample code provided by Microsoft
Replaces some variables with my Client_Id and Secret
Ran the code
The code returns an access token but the authorization requests fails with 401 - Unauthorized: Access is denied due to invalid credentials.
Here's the Python code I'm using.
import msal
config = {
"authority": "https://login.microsoftonline.com/consumers",
"client_id": "<my client ID>",
"scope": ["https://graph.microsoft.com/.default"],
"secret": "<My secret stuff>",
"endpoint": "https://graph.microsoft.com/v1.0/users"
}
# Create a preferably long-lived app instance which maintains a token cache.
app = msal.ConfidentialClientApplication(
config["client_id"], authority=config["authority"],
client_credential=config["secret"],
)
result = None
result = app.acquire_token_silent(config["scope"], account=None)
if not result:
result = app.acquire_token_for_client(scopes=config["scope"])
if "access_token" in result:
# Calling graph using the access token
graph_data = requests.get( # Use token to call downstream service
config["endpoint"],
headers={'Authorization': 'Bearer ' + result['access_token']}, ).json()
print("Graph API call result: ")
print(json.dumps(graph_data, indent=2))
else:
print(result.get("error"))
print(result.get("error_description"))
print(result.get("correlation_id")) # You may need this when reporting a bug
According to the error message, I'm obviously missing something in the authorization process but can't tell what. I'm not even sure about the Authority and Endpoints I should use. My account being a personal one, I have no tenant.
Do I need to set-up / configure some URI somewhere?
Any help would be welcome.
Thank you in advance.
In your client app you need to store the token that you are getting from the MSAL. and then send the token with an authorized request.
For OneDrive, download the OneDrive for python. You can see the different option for Authentication.
The reason you are getting an access token, ID token, and a refresh token is because of the flow you're using. My suggestion is to review the flows for a better understanding of how the authentication process works and what will be returned accordingly. You can use this MSAL library for python.
When i visit the endpoint '/api/v1/users/me/data/csv', i receive the following message:
{
"error": {
"title": "Unauthorized",
"message": "You are not authorized to perform that action. Please use the api_key
parameter with your registered key.",
"status": 401
}
}
The endpoint is supposed to go to the buckets and write data as a CSV that the user can download. I am not sure what "api_key" they are referring to here.
Could this just be that i am not using accessing the correct bucket or is it that i am not using the correct key?
To verify which Key it is Check the logs on App Engine to see if the call got all the way to App Engine.
To Check the App Engine Logs do the following:
Go to Console
Go to App Engine >> Versions
For the serving version go to Tools >> Logs
This will Open the logs for that version and if the calls are getting to app engine you will see the invocations there. If you don't see any invocation it is because they are getting stopped by Cloud Endpoints.
This Error is usually triggered by Cloud Endpoints when you specify APIkey Security for the path and calling it without key parameter or with a wrong key.
I've created a script for Uber and it worked fine until my access token expired.
So here's this piece of code (almost similar to Uber SDK https://github.com/uber/rides-python-sdk):
session = Session(oauth2credential=OAuth2Credential(
client_id=credential_dict.get('client_id'),
access_token=credential_dict.get('access_token'),
expires_in_seconds=credential_dict.get('expires_in_seconds'),
scopes=credential_dict.get('scopes'),
grant_type=credential_dict.get('grant_type'),
redirect_url=credential_dict.get('redirect_url'),
client_secret=credential_dict.get('client_secret'),
refresh_token=credential_dict.get('refresh_token')))
client = UberRidesClient(session)
With the expired token I can not do anything further, it returns
uber_rides.errors.ClientError: 401: No authentication provided.
Also, I'm confused by "The SDK will handle the token refresh for you automatically when it makes API requests with an UberRidesClient."
How can I get my new access token using refresh token? I can authorize again and it works but is annoying.
You can get new access token if you have valid refresh token by using the token endpoint: https://login.uber.com/oauth/v2/token. For more information check the Uber documentation.
"When the user’s access_token has expired, obtain a new access_token by exchanging the refresh_token that is associated with the access_token using the Token endpoint".
I am trying to fetch captions from YouTube video using YouTube Data API (v3)
https://developers.google.com/youtube/v3/guides/implementation/captions
So, first I tried to retrieve a captions list using this url:
https://www.googleapis.com/youtube/v3/captions?part=snippet&videoId=KK9bwTlAvgo&key={My API KEY}
I could retrieve the caption id that I'd like to download (jEDP-pmNCIqoB8QGlXWQf4Rh3faalD_l) from the above link.
Then, I followed this instruction to download the caption:
https://developers.google.com/youtube/v3/docs/captions/download
However, even though I input the caption id and my api key correctly, it shows "Login Required" error.
I suppose I need OAuth authentication, but what I am trying to do is not related to my users's account, but simply downloading public caption data automatically.
My question is: Is there any way to process OAuth authentication just once to get an access token of my own YouTube account and then reuse it whenever I need it in my application?
I can't speak to the permissions needed for the captions API in particular, but in general, yes, you can OAuth to your app once using your own account and use the access and refresh tokens to make subsequent OAuth'd requests to the API. You can find the details of generating tokens here:
https://developers.google.com/youtube/v3/guides/auth/server-side-web-apps#Obtaining_Access_Tokens
To perform the steps manually (fortunately, you only need to do this once):
If access has already been granted for an app, it needs to be removed so that new auth credentials can be established. Go to https://security.google.com/settings/security/permissions (while logged into your account) and remove access to the app. If the client ID or secret change (or you need to create one), find them at https://console.developers.google.com under API Manager.
To grant access and receive a temporary code, enter this URL in a browser:
https://accounts.google.com/o/oauth2/auth?
client_id=<client_id>&
redirect_uri=http://www.google.com&
scope=https://www.googleapis.com/auth/youtube.force-ssl&
response_type=code&
access_type=offline&
approval_prompt=force
Follow the prompt to grant access to the app.
This will redirect to google.com with a code parameter (e.g.,
https://www.google.com/?code=4/ux5gNj-_mIu4DOD_gNZdjX9EtOFf&gws_rd=ssl#). Save the code.
Send a POST request (e.g., via Postman Chrome plugin) to https://accounts.google.com/o/oauth2/token with the following in the request body:
code=<code>&
client_id=<client_id>&
client_secret=<client_secret>&
redirect_uri=http://www.google.com&
grant_type=authorization_code
The response will contain both an access token and refresh token. Save both, but particularly the refresh token (because the access token will expire in 1 hour).
You can then use the access token to send an OAuth'd request manually, following one of the options here, essentially:
curl -H "Authorization: Bearer ACCESS_TOKEN" https://www.googleapis.com/youtube/v3/captions/<id>
or
curl https://www.googleapis.com/youtube/v3/captions/<id>?access_token=ACCESS_TOKEN
(When I tried the second option for captions, however, I got the message: "The OAuth token was received in the query string, which this API forbids for response formats other than JSON or XML. If possible, try sending the OAuth token in the Authorization header instead.")
You can also use the refresh token in your code to create the credential needed when building your YouTube object. In Java, this looks like the following:
String clientId = <your client ID>
String clientSecret = <your client secret>
String refreshToken = <refresh token>
HttpTransport transport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(transport)
.setJsonFactory(jsonFactory)
.setClientSecrets(clientId, clientSecret)
.build()
.setRefreshToken(refreshToken);
try {
credential.refreshToken();
} catch (IOException e) {
e.printStackTrace();
}
youtube = new YouTube.Builder(transport, jsonFactory, credential).build();
I imagine you can do something similar in Python with the API Client Libraries, although I haven't tried Python.