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.
Related
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!
problem description:
we are getting (#100) Missing permissions errors while extracting facebook account ads
insights data using programmatically generated access tokens using Graph API in python.
later we generated access tokens in the app with ads_read and insights_read permission and we can able to extract the data successfully.
questions:
1.how can we generate access tokens with permissions programmatically using Graph API in python?
2.which token is advisable to extract data for ad account insights?
error message:
{
"error": {
"message": "(#100) Missing permissions",
"type": "OAuthException",
"code": 100,
"fbtrace_id": "A4vPClDlI__dFmxxhiVVGRG"
}
}
access token generation code sample:
import requests
def get_fb_token(app_id, app_secret):
url = 'https://graph.facebook.com/oauth/access_token'
payload = {
'grant_type': 'client_credentials',
'client_id': app_id,
'client_secret': app_secret
}
response = requests.post(url, params=payload)
return response.json()['access_token']
app_id = 'XXXXXXXXXXXXXXX'
app_secret = 'XXXXXXXXXXXXXXXXX'
data_request = get_fb_token(app_id, app_secret)
print(data_request)
Note:
we have also tried passing scope:ads_read, but we are getting the same error.
we have also tried Facebook -SDK package, but we are getting the same access tokens.
Simplest: If your BM has access to that ad account
Use System User flow.
Create A System User.
Generate&Copy the long lived token from BM page and paste it into your server. (This will not expire ever)
Assign the ad accounts(or any other assets) you wanna access either programmatically or manually.
Standard Apporach: Oauth2 flow.
When users get onboarded to your system, ask them to sign in via FB and send the short lived token to Backend servers. OAuth2
Exchange the short lived token for long lived one with FB. Long lived tokens have expiry of 60days.
Goal:
I have a cloud function that impersonates a service account based on the service account email provided to it. I then want to use the impersonated service account to sign a jwt.
What I tried:
I have set up the impersonation of the service account like this:
credentials = google.auth.impersonated_credentials.Credentials(
source_credentials=SOURCE_CREDENTIALS,
target_principal=SA_EMAIL,
target_scopes=TARGET_SCOPES,
lifetime=300)
This brings me to a sub question: What target scopes do I need to specify?
After creating the impersonated credentials, I try to use signer (docs) to sign the payload of the JWT:
payload = {
'iat': now,
"exp": now + expiry_length,
[...]
}
signer = target_credentials.signer
jwt = google.auth.jwt.encode(signer, payload)
The error message I receive is:
AttributeError: 'Credentials' object has no attribute 'key_id'
Question:
I suspect I am not on the right track with my approach using signer.
How is it possible to achieve my goal?
In your example code, you have only create the payload section. A signed JWT also requires a header.
The header looks like this:
header = {
'kid': pkey_id, # Signing Private Key ID
"alg": "RS256", # Google uses SHA256withRSA
"typ": "JWT"
}
The header and payload are base64 encoded and then concatenated with a dot (period symbol) in between. You sign the combined data.
The problem that you will have is that you need to private key id (pkey_id in my example). That value is located in the service account JSON key file. However, Google does not publish the JSON key file that is used for signing. The key used is private to Google. You can get the private key by signing some data first as the pkey_id is returned as part of the response. Then sign your JWT.
I recommend that you switch from using the Sign Blob API and use the SignJwt API instead. The SignJwt API does not require that you create a JWT header.
IAM Service Account Credentials API
Method: projects.serviceAccounts.signJwt
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.
I am currently able to generate a token from Docusign's API.
I am using the python wrapper docusign-esign.
{
'access_token': <JWT token>,
'data': None,
'expires_in': '3600',
'refresh_token': None,
'scope': None,
'token_type': 'Bearer'
}
For Developers: API and Integration Key Information
Using
Implicit Grant
RSA Keypairs
redirect URI set
status LIVE
BASE_URL='https://demo.docusign.net/restapi'
OAUTH_BASE_URL='account-d.docusign.com'
I was using the envelope API to get envelope status with auth header as
'Authorization Bearer <JWT token>'
I get the following 400 error:
{
"errorCode": "PARTNER_AUTHENTICATION_FAILED",
"message": "The specified Integrator Key was not found or is disabled. Invalid account specified for user."
}
The public ID, integrator key, API Account ID and API Username are all separate IDs and are used at a different moment when making API calls. This has caused me a huge amount of frustration when dealing with the API.
To help clarify (this is specific to python's wrapper for Docusign):
when using request_jwt_user_token
it requires
client_id -- integrator key
user_id -- ID you want to impersonate, which can be found in the admin page > users > API Username (which is a UUID)
oauth_host_name -- account-d.docusign.com for dev or account.docusign.com for production
private_key_bytes -- the RSA Keypairs in the file (private key)
scopes -- typically signature impersonate for JWT implicit grant
then when using the EnvelopeAPI.create_envelope it required an account_id, which was not the client_id nor user_id. The account_id for me was the API Account ID for in For Developers: API and Integration Key Information. So either copy and paste the API Account ID from docusign or get it using the JWT grant example here
This was probably totally my fault for not understanding it, but hopefully, this is some info that can help someone else.
do you actually replace with a JWT token? and how did you generate this token?
Please make sure you read and follow the instructions here - https://github.com/docusign/eg-01-python-jwt