I have been trying to create a connection with the gmail api. It worked when I followed this example: https://developers.google.com/gmail/api/quickstart/nodejs
The problem is, this requires the user to browse to a URL and then enter an authentication code in the CLI. This is possible on my local dev machine, but I don't see how this should be done when deployed on a production server, in a docker container. Additionally this method requires you to store a file in your project folder containing your credentials (sensitive data that I don't want to have in my Dockerfile obviously).
My second attempt was using JWT. I followed these steps Send mail via Google Apps Gmail using service account domain wide delegation in nodejs. This works until I actually try to retreive the email from the inbox. I get an error saying GaxiosError: unauthorized_client: Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.. I have created a service account with domain wide delegation so the account should be authorized to do anything.
Then I read this:
"Service accounts only work with GSuite because you have to be able to preauthorize the service account and grant it access to the users account. There is no way to preauthorize a normal user Gmail account. So no you cant use a service account with a normal users gmail account." source: Client is unauthorized to retrieve access tokens using this method Gmail API C#
I have also looked at using just an api key, but this option is not available for gmail.
How the hell am I supposed to authenticate from my container?
So it turns out the account I was using didn't have the correct rights. We did have a gsuite. Everything is working as expected now! :)
Related
Background
I have a google sheet, who's data I need to process on my local system. The nature of processing is very tedious and long so I wrote a script for it.
Problem
I need to access the google sheet through the python script to process it further. Online it is mentioned that to read the private google sheet directly, I need to create a GCP project and within that project, I need to create a service account. After that I should download the credentials and share the google sheet with that service account email.
Two problems here are :
Downloading the credentials -- insecure and my organization prohibits it.
Sharing of google sheet with service account email. organization also prohibits sharing sheet with outside organization emails.
What I found as a solution
I came across a solution of impersonating a service account but I could not find anything as to how can I do that. (Would appreciate any insights on that). All the other solutions suggested to download credentials which is a big NO.
For the sharing of sheets thing, I guess we can use drive API, but same problems are with that.
I tried using gcloud auth login and gcloud auth application-default login but was getting errors
Request had insufficient authentication scopes.". Details: "Insufficient Permission: Request had insufficient authentication scopes.
using ['https://www.googleapis.com/auth/spreadsheets', https://www.googleapis.com/auth/drive'] as scopes
What I need? (Summary)
How to access google sheets API (or download the Sheet from google drive) without downloading any sort of credentials.json.
problem
Your only option to access private user data is to be authorized as a user who can access the file. Either logging in using Oauth2 or using a service account
Downloading the credentials -- insecure and my organization prohibits it.
In order to use a google api you must first register your application on google developer console and download the client credentials then a user must authorize the application using Oauth2, which would mean both downloading the credentials.json file from google developer console and you getting user token credentials from the authorized user.
Sharing of google sheet with service account email. organization also prohibits sharing sheet with outside organization emails.
In order to use a service account you would again need to first register your application on google developer console and download the client credentials for the service account. Then you would need to share the sheet with the service account.
service account impersonation.
Service account impersonation is used by GSuite domain. You create a normal service account again downloading the credentials, and then the GSuite admin is able to delegate authority to the service account which will allow it to impersonate a user on the domain.
This would require you to have GSuite domain and the owner of the file being also on the GSuite domain, and you creating a project on google developer console and downloading the credentials.json for the service account, which you already stated you couldn't do.
conclusion
I guess what i am saying is there is no way with the limitations imposed by your organization for you to access a private google sheet or any private user data on googles system, via any api.
I assume you're looking at an example that looks a bit like this:
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
SCOPES = ['https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/drive']
def main():
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
drive_svc = build('drive', 'v3', credentials=creds)
sheets_svc = build('sheets', 'v4', credentials=creds)
The library does it for you in two lines of code, but you can read the details of how this works at:
OAuth 2.0 for Mobile & Desktop Apps
The credentials.json file mentioned above is not an authorized set of user credentials. It consists of a client ID (public) identifier for your application and a client secret (private) known only to your application. Neither of these can be used to access your data, but they can be used to ask a user for permission to allow app access.
Your organization may have a policy disallowing data access from untrusted applications. In that case, you'll need your admin to trust your application (and your client ID). That's how the policy is intended to work.
A quick note on service accounts in Google Drive:
See the warning at Drive API - Authenticate your users. Generally speaking, service accounts should never act as themselves in Drive. They should only be used from an administrative capacity to impersonate users. They aren't, and shouldn't be relevant to your use case.
We use Azure Logic Apps that are deployed from DEV to TEST to PROD using powershell scripts. Thoe Logic Apps use API connections.
For certain API connections we want to use a different Service User instead of my personal account. So if a Logic App sends an E-Mail it should send it as Service User and not myself. The special thing about API connections is, that Azure forces you to re-authenticate them after deployment by powershell script. So after each deployment you need to re-authorize API connections.
I successfully managed to authenticate using powershell script with the sample mentioned here: https://github.com/logicappsio/LogicAppConnectionAuth
However, it will always somehow authorize me on with my Windows account. I am not able to log in as someone else. When the Azure Logon Window appears and I enter the service users name, but it will then not ask me for the passwort, it will authorize the connection with my personal user right after entering a username.
How can I use Azure powershell commands to perform connection authorization as a different user?
I was hoping someone could point me into a better direction (google keywords, etc.) on how to authorize API connection as a different user.
I understand your question is about authorizing API connections with different user account or service accounts. The behavior you specified above is specifically for office 365 connection. Authorization mechanism differs in different set of connectors.
However, for using service accounts to authorize Office 365 API connections, we need to make sure that browser cache doesn't use the Windows/Azure logon credentials automatically.
You can clear the browser cache and do the authorization from a private browser.
If that doesn't help you, there is a hack that's explained in this blog.
https://techcommunity.microsoft.com/t5/integrations-on-azure/using-service-account-for-office-365-outlook-connector/ba-p/1978513
Let me know if you have any questions.
Haris
I want to use Google Drive API, Sheet API, Gmail API in my Python program.
I follow this page. It says
"Create credentials to use the Google Drive API
After Enabling the Google Drive API, Google should take you to the Google Drive API console for your project.
Click Create credentials."
It will create credentials for using only Drive? I read a lot of docs, official, blogs, tutorials, etc. I'm beginner in this topic, so please give some details also, because not everything is clear for me.
There are four types of credentials and they are used for different purposes and require different code to use them.
Browser credentials used for applications which will be hosted on a website. For use with accessing private user data.
Native credentials (other) used for installed applications. ex: A windows desktop application. For use with accessing private user data.
Service account credentials used for server to server communication where the developer has access to the account which will be accessing the API.
Mobile applications.
The first thing you need to do is decide whose data you will be accessing. Are you expecting to access a users data then you will need to use OAuth2 and request the users permission to access the data. If you are acting a static drive account and only that account and you personal have access to set it up you could use a service account.
Browser credentials
Uses OAuth2 to request permission of a user to access their data. Response will be returned to a web site. web app sample
Native credentials
Use OAuth2 to request permission of a user to access their data. Response will be returned to the host where it was sent from. installed app
Service account credentials
Service accounts are dummy users which we as developers can use to pre-authorize a user with access. This method will not require user sign-in or consent. service account
Note
You will probably only need to create one credential type. You will need to enable all of the APIs you intend to use in the Google Developer Console. (Google Drive API, Sheet API, Gmail API) You should know that service accounts do not support gmail API unless you have a GSuite account and can set up the authorization.
You will need to create a service for each of the API types.
drive = build('drive', 'v2', credentials=credentials)
sheets = build('sheets', 'v2', credentials=credentials)
gmail = build('gmail', 'v2', credentials=credentials)
I'm curious if it's possible to gain access to the Gmail settings of all users within a domain once a user with Admin access authenticates. I know using the Admin SDK, you have access to user settings, however, I'd like to setup email forwarding and it doesn't seem like it's possible without each user authenticating.
You may refer with this SO thread. Before you can call the Gmail API you need to use the service account "JWT flow" in your code to retrieve an OAuth2 credential for the Gmail user you want to access. Here is the documentation. You may also check this related post.
I've developed a feature on my web-site that allow to log-in using Azure.
So users in my web-site can sign-in using:
Azure (OAuth2). We're using a multi-tenant app. We're just using the application to log in users. So we don't really use the Access-Token to make requests. We just use the access-token to obtain the user email (decoding it with JWT).
Their own email-password they can set on my site.
This creates a problem:
Imagine an person that starts working in a company. The IT team give him an email that belongs to their azure account (with their account domain). This team also have an account on my site (configured with the same domains they use on Azure). So this user will try to log in my site using his credentials. We'll create his profile on their company account (due to the email domain). He sets his password. Sometimes he use Azure to log-in and sometimes he use his email-password to log-in.
The next month and, this person get fired. The IT team delete him from Azure. Although, the IT team forget about deleting him also on my site. So this user has permissions to sign-in with his email-password credentials and still be able to see private information (he can even delete private files).
I would like to know if there is a way to sync my app with every Directory that is using it. So I would be able to receive user action notifications (like user deletions). It would be great to receive a call to an endpoint with information about users important actions. This way we'll be able to delete the user also from our platform. So the company can forget about deleting an user on my site without having the stolen-information problem.
PS: I've seen you have a logout sync using SAML, but I wonder if we would be able to receive other kind of notifications, because we don't want to log-out the user when this logs-out from Azure.
If you have permission from the ex-user tenant administrator to access their directory, you can check if the user is listed or not by using Microsoft Graph API
I've been talking with microsoft support and there is no way of having microsoft calling our endpoint to receive some notifications.
So the only solution is ask for admin permission or, having the refresh_token from Oauth2, check the user still appears on Graph (https://graph.microsoft.com/v1.0/me).