Google Drive users do not have permissions to read file - node.js

I would like to create an application where the users could access to all my data in Google Drive.
I have implemented a 2-legged OAuth to obtain all the data from Google Drive with my server app with no user authorization. The server can obtain all the data with the 2-legged OAuth.
The problem arrives when using, for example, the link of a drive document, the users connected to my app cannot access it due to they have no permissions.
I would like to know if it is mandatory give them permissions to access the files or maybe there is another service provided by google to have a comun storage for all the users without get the authorization or permissions for every single user.
I would like to know to if it is posible to use the Drive interface to show the users the documents.

There are actually three ways to access Google data.
Api key used to access public data.
Oauth2 used to access private data. Prompts for user to give permissions to access data and grants a refresh token.
Service accounts. Service accounts are preauthorized. there is no prompt to request a user permission to access the data.
I am not exactly sure what you mean by 2-legged Oauth. It sounds like you are talking about a service. You can grant the service account access to your personal drive account by sharing one or more folders with it. Note: I am not sure if you can share the root folder or not.
When you wish to allow one of your users to access a file you should have the service account add the user as reader of the file then they will have access. this can be done by inserting permissions.
Note. I am not a Node.js developer and I am not sure that service accounts are supported by Node.Js you may have to switch to a server sided language I don't know enough about it.
I do have a blog post that explains service accounts in more detail.

Related

Basic Microsoft Graph App to retrieve a shared Excel File

I am trying to understand Microsoft Graph APIs but I found them kind of confusing. There's an excel file that is shared with me on OneDrive. I want to download it using Microsoft Graphs. I was able to generate the app and set up its configurations and permissions so that I can send a request and get an authorization token that I can use to send requests.
However, I have a couple problems, even in Graph Explorer, which I use as my account, not as the app.
To find out the file Id that is shared with me, I used the "files shared with me" API that is under OneDrive. (https://graph.microsoft.com/v1.0/me/insights/shared)
I copied the id that I get from there and used it in "worksheets in a workbook" API under Excel category. https://graph.microsoft.com/v1.0/me/drive/items/{drive-item-id}/workbook/worksheets)
However I got Item Not found error. The problem is, even though I can see it on oneDrive as a shared object I can't seem to open it using the second API.
How can I download the Excel file that is shared with me through OneDrive? Which API should I use? The app that will send the requests is a standalone app that will send the requests without human authorization. I don't know the correct terminology here but Microsoft doesn't allow it to have a /me request, it gets "/me request is only valid with delegated authentication flow.", therefore I probably need someway for app to see that oneDrive link. But I was unable to find a working way.
The error message "/me request is only valid with delegated authentication flow." means what it says. There are two main ways to authenicate a application with the graph API. Application authenication and On behalf of user authencitation. So the error message is telling you that you are using the application authenication and the API path /me is only accessable with On behalf of user authencitation (e.g. delegated authentication). This makes sense because when using the application authenication who is me?
The API endpoints says what authentication types they support. If you take the worksheets API it says under permissions section:
Permission type - Permissions (from least to most privileged)
Delegated (work or school account) - Files.ReadWrite
Delegated (personal Microsoft account) - Not supported.
Application - Not supported.
Which is telling us that Application and Delegated for personal Microsoft accounts are not supported and that Delegated for work/school accounts requires the Files.ReadWrite permission.
To download the drive item you can use the download item API.
This supports both Application and Delgated permissions. For Application permisions you will not be able to use the /me path though. You will most likely have to use something like:
/users/{userId}/drive/items/{item-id}/content
I am assuming your file is stored in a work account one drive storage and not in one of the other storage places (AD group, etc).

How to read private Google Sheets using Google Sheets API without service account or downloading credentials

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.

Which credentials should I choose and how?

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)

Sync with Azure Active Directory with a multi-tenant app (receiving user notifications)

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).

Secure login to a website on Azure with Windows authentication and username/password

I want to set up a website on Azure according to the following requirements and are wondering if it is even possible?
As a internal team member, I must be able to login to the site with Windows Authentication
As a external customer, I must be able to login to the site with user name and password
As a external customer, I must not be able to access a subset of the site
As a unauthorized user, I must not be able to access anything on the site
I guess I have to set up a VPN connection between Azure and the Active Directory in my company. How do I do that?
Is it at all possible to meet my requirements?
Background Information
We are a small project with about 10 team members.
We have four large customers who need access to the site, and there are a few people in each customer who needs to have access to the site.
Customers will just have read only access to static, non-sensitive information.
The team members will have write access, and will also handle some sensitive information.
** Edit **
I have now managed to create efficient synchronization of our projects local AD to Azure, thanks user18044. Unfortunately, the accounts for the team members is located in the company's AD (corp.mycompany.com), and out AD has one-way trust with it.
We have groups in the project-AD pointing to our accounts in the company's AD, but the members in the groups is not synchronizing over to Azure.
Can this be solved?
Yes, I think what you are describing is doable.
Your first two bullet points are about authentication. As Azure Active Directory does not directly support Windows Authentication, federation is the way to go here.
When you as an internal team member log on, you land on what is called a home-realm discovery page, where you pick the realm you want to authenticate in. Picking the realm of your company, you get redirected to the STS (for example ADFS) your company has set up to authenticate you. If you are in the same Windows Active Directory network as the STS is authenticating against, you should be able to use Kerberos to be issued a token.
An external customer would be redirected to another STS that would use forms authentication against a credential store to issue security tokens.
Both security tokens are then posted back to Azure Active Directory which is configured to trust both STS's and issues a token of its own. See here for an example.
As for the second two bullets, the authorization part you can do based on roles you assign to your users. Depending on which STS authenticated your user, you assign them a certain role. Based on that role you can give access to certain parts of your website or not. How to implement this depends on what stack you are using for your web application, but a Google search should give you some leads.

Resources