I am looking for collect data from Google ADS API into GCP by using Python scripts and it requires to fill these items for authentication in the google-ads.yaml file:
developer_token:
client_id:
client_secret:
refresh_token:
login_customer_id:
I was able to fill these items by asking people in my company or generating it with google python scripts in GitHub but I need to understand the role of each, the docs seems to be disperse with a long learning path.
You can follow this guidebook to make your google-ads.yaml file. And for the sample role you provided, below are the definitions of each but you can check this sample template for more details about it.
Developer token
A developer token is required when making requests to the Google Ads API regardless of whether you're using the OAuth2 or Service Account configurations. To obtain a developer token see: https://developers.google.com/google-ads/api/docs/first-call/dev-token
developer_token: INSERT_DEVELOPER_TOKEN_HERE
OAuth2 configuration
The below configuration parameters are used to authenticate using the recommended OAuth2 flow. For more information on authenticating with OAuth2 see:
https://developers.google.com/google-ads/api/docs/oauth/overview
client_id: INSERT_OAUTH2_CLIENT_ID_HERE
client_secret: INSERT_OAUTH2_CLIENT_SECRET_HERE
refresh_token: INSERT_REFRESH_TOKEN_HERE
Login customer ID configuration
Required for manager accounts only: Specify the login customer ID used to authenticate API calls. This will be the customer ID of the authenticated manager account. It should be set without dashes, for example: 1234567890 instead of 123-456-7890. You can also specify this later in code if your application uses multiple manager account + OAuth pairs.
login_customer_id: INSERT_LOGIN_CUSTOMER_ID_HERE
Related
I'm trying to use a service account and the Google Drive API to automate sharing a folder and i want to be able to set the expirationTime property.
I've found previous threads that mention setting it in a permissions.update() call, but whatever i try i get the same generic error - 'Expiration dates cannot be set on this item.'.
I've validated i'm passing the correct date format, because i've even shared manually from my drive account and then used the permissions.list() to get the expirationTime from the returned data.
I've also tried creating a folder in my user drive, making my service account and editor and then trying to share that folder via API but i get the same problem.
Is there something that prevents a service account being able to set this property?
To note - I haven't enabled the domain wide delegation and tried impersonating yet.
Sample code:
update_body = {
'role': 'reader',
'expirationTime': '2023-03-13T23:59:59.000Z'
}
driveadmin.permissions().update(
fileId='<idhere>', permissionId='<idhere>', body=update_body).execute()
Checking the documentation from the feature it seems that it's only available to paid Google Workspace subscriptions as mentioned in the Google Workspace updates blog. You are most likely getting the error Expiration dates can't be set on this item as the service account is treated as a regular Gmail account and you can notice that this feature is not available for this type of accounts in the availability section of the update:
If you perform impersonation with your Google Workspace user I'm pretty sure that you won't receive the error as long as you have one of the subscriptions in which the feature is enabled. You can check more information about how to perform impersonation and Domain Wide Delegation here.
I am currently using AWS Cognito for user authentication. However, I have plans to make AuthN IDP agnostic. For example, I want to be able to replace Cognito with some other identity provider later.
Currently, I use boto3 cognito API to get idToken like below. How can I write a non-cognito specific implementation to get idTokens so that when the provider changes, I won't be relying on cognito? I want to use some generic python OAuth APIs to obtain idToken for the user. How can I do that?
cognito_client = boto3.client('cognito-idp')
response_tokens = cognito_client.initiate_auth(
AuthFlow='USER_PASSWORD_AUTH',
AuthParameters={
'USERNAME': uname,
'PASSWORD': pwd
},
ClientId=OAUTH_AUDIENCE
)
To get ID token from Cognito you need to call a specific API. And if you want to switch to other IDP later, then you need to use other API provided by that IDP. So, APIs are specific to the IDP.
Hence, as at this moment you want token from Cognito, you need to use AWS APIs.
That said, in case by "different IDP" you mean to say "configuring different IDP with Cognito" then I would like to add that, OAuth 2.0 flow can not be made using CLI or SDKs. Cause, OAuth 2.0 flow is a browser based flow and to login with different IDP you need to use browser.
Goal:
I have set up a Google API Gateway. The backend for the API is a cloud function (written in python). The cloud function should query data from Google BigQuery (BQ). To do that, I want to create a BQ Client (google.cloud.bigquery.Client()). The API should be accessed by different applications using different service accounts. The service accounts have permission to access only specific datasets within my project. Therefore, the service accounts/applications should only be able to query the datasets they have the permission for. Therefore, the BQ Client within the cloud function should be initialized with the service account that sends the request to the API.
What I tried:
The API is secured with the following OpenAPI definition so that a JWT signed by the service account SA-EMAIL is required to send a request there:
securityDefinitions:
sec-def1:
authorizationUrl: ""
flow: "implicit"
type: "oauth2"
x-google-issuer: "SA-EMAIL"
x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/SA-EMAIL"
x-google-audiences: "SERVICE"
For the path that uses my cloud function, I use the following backend configuration:
x-google-backend:
address: https://PROJECT-ID.cloudfunctions.net/CLOUD-FUNCTION
path_translation: CONSTANT_ADDRESS
So in the cloud function itself I get the forwarded JWT as X-Forwarded-Authorization and also the already verified base64url encoded JWT payload as X-Apigateway-Api-Userinfo from the API Gateway.
I tried to use the JWT from X-Forwarded-Authorization to obtain credentials:
bearer_token = request.headers.get('X-Forwarded-Authorization')
token = bearer_token.split(" ")[1]
cred = google.auth.credentials.Credentials(token)
At first, this seems to work since cred.valid returns True, but when trying to create the client with google.cloud.bigquery.Client(credentials=cred) it returns the following error in the logs:
google.auth.exceptions.RefreshError: The credentials do not contain
the necessary fields need to refresh the access token. You must
specify refresh_token, token_uri, client_id, and client_secret.
I do not have much experience with auth/oauth at all, but I think I do not have the necessary tokens/attributes the error is saying are missing available in my cloud function.
Also, I am not exactly sure why there is a RefreshError, since I don't want to refresh the token (and don't do so explicitly) and just use it again (might be bad practice?).
Question:
Is it possible to achieve my goal in the way I have tried or in any other way?
Your goal is to catch the credential that called the API Gateway, and to reuse it in your Cloud Functions to call BigQuery.
Sadly, you can't. Why? Because API Gateway prevent you to achieve that (and it's a good news for security reason). The JWT token is correctly forwarded to your Cloud Functions, but the signature part has been removed (you receive only the header and the body of the JWT token).
The security verification has been done by API Gateway and you have to rely on that authentication.
What's the solution?
My solution is the following: In the truncated JWT that you receive, you can get the body and get the Service Account email. From there, you can use the Cloud Functions service account, to impersonate the Service Account email that you receive.
Like that, the Cloud Functions service account only needs the permission to impersonate these service account, and you keep the permission provided on the original service account.
I don't see other solutions to solve your issue.
The JWT that you are receiving from API Gateway is not an OAuth Access Token. Therefore the JWT Payload portion is not a credential that you can use for the BigQuery Client authorization.
As #guillaume blaquiere pointed out, the Payload contains the email address of an identity. If the identity is a service account, you could implement impersonation of that identity. This could be a good solution if you are using multiple identities with API Gateway. If the identity is a user account, then you would need to implement Domain-Wide Delegation.
I recommend simply using the service account assigned to the Cloud Function with proper roles assigned to initialize the BigQuery client. Provided that API Gateway is providing authorization to reach your Cloud Function, there is no need for the extra layer of impersonation.
Another option is to store the matching service account JSON key file in Secret Manager and pull it when required to create the BigQuery Client.
In my company, I need to upload Excel files on OneDrive.
We have a 365 Business Plan and every employee has an own 365 account, but I want to maintain just one repository for merged files and avoid to share the same repos account among all, so I prefer to implement a "access without user" through client credentials flow.
The first problem that I've met is the authorization: when I try to authorize the app by /adminconsent endpoint, it fails because my client account is not an administrator :-( So I've tried to use another account, a simple Microsoft Account (for that I've made a new registration of the app in the Application Portal) but when I try to authorize the app I receive this error:
"AADSTS50020: We are unable to issue tokens from this API version for a Microsoft account. Please contact the application vendor as they need to use version 2.0 of the protocol to support this."
What's wrong?
As an alternative, I've thought to continue with 365 Business employee accounts, create a folder with a tech account and share it, but when using Graph Explorer with an employee account and make the request
/me/drive/sharedWithMe
I receive just the shared folder but without the content
Here the code (I'm using the requests_oauthlib Python module):
In the beginning, I initialize the class object
client = BackendApplicationClient(client_id=config.CLIENT_ID)
self.oauth = OAuth2Session(
client.client_id,
scope=config.SCOPES,
redirect_uri='https://me.local/allowed')
then I make a request for authorization_url
auth_base = 'https://login.microsoftonline.com/common/adminconsent'
self.authorization_url, state = self.oauth.authorization_url(
auth_base,
state="12345")
return self.authorization_url
and the request for the token
return self.oauth.fetch_token(
token_url=https://login.microsoftonline.com/common/oauth2/v2.0/token',
client_id=config.CLIENT_ID,
scope="https://graph.microsoft.com/.default",
client_secret=config.CLIENT_SECRET,
authorization_response='https://me.local/authorized'
)
You need to be a tenant administrator in order to consent application only access (where you only use client id and secret). However, you can use alternative flows such as Resource Owner Credentials Grant and On-Behalf-Of Grant which requires you to have the credentials of a user with relevant permissions.
You can also read about those flows in my post:
Getting Access Token for Microsoft Graph Using OAuth REST API.
Regarding the message with "version 2.0" - it may be caused by a mixup between version 1 and version 2 of the Microsoft OAuth API. Version 1 is only meant for organization users (users which sit inside azure active directory) and version 2 support Microsoft accounts as well. You can read more about the difference between the two versions in here. Make sure you use one of those versions for the entire process (creating the app, assigning and consenting permissions, and requesting an access token). Mixing between the two versions may not work.
The instagram api returs this when triying to get latest post by hashtag:
{"pagination":{"deprecation_warning":"next_max_id and min_id are deprecated for this endpoint; use min_tag_id and max_tag_id instead"},"meta":{"code":200},"data":[]}
This is the url I use for the query:
https://api.instagram.com/v1/tags/paris/media/recent?access_token=ACCESTOKENHERE
I tried using someone else access token and it works well. What is causing this?
I'm having the same issue. It seems that Instagram apps in "Sandbox Mode", i.e. those created after 17 November do not have access to public_content.
This is why using an access code of another app (presumably one that isn't in Sandbox mode) works.
For apps registered after Nov 17, 2015. A few endpoints return different data in Sandbox mode. The endpoint you are using is also one of them. Unless your app goes live, you can't fetch public content
As another example, let's consider an endpoint that returns a list of media: /tags/{tag-name}/media/recent. The response returned by this endpoint will contain only media with the given tag, as expected. But instead of returning media from any public Instagram user, it will return only media that belongs to your sandbox users, restricted to the last 20 for each user.
Source: http://instagram.com/developer/sandbox/
I'm having the same problem with PHP (language doesn't matter by the way). I saw on the Sandbox page these 3 conditions:
Apps in sandbox are restricted to 10 users
Data is restricted to the 10 users and the 20 most recent media from each of those users
Reduced API rate limits
You can only get the data from sandbox users, whom you can invite via the Manage Clients section.
Visit Manage Clients.
Click edit for your app.
Go to the Sandbox tab.
Add some users to invite.
Get them to accept the invitation and auth (make sure you have the scopes set up properly!).
Rejoice in the glory of their data.
Use an access_token with permission public_content. Just direct the user to your authorization URL with scopes:
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code&scope=basic+public_content
to get the permission.
Read more about Login Permissions (Scopes).