Google Drive API for iOS: OAuth2.0 with an application-owned account - ios

I'm creating a simple iPhone app. The basic premise is that the app will display some data (That I provide online) on the application. The data changes over time, so the app has to draw the data from online and display it. I don't have a significant programming background so I don't want to use my own server.
Thus, I thought it would be significantly easier to just put the data into some documents on a Google account and then access them programmatically via the Google Drive API. I could then update the data in my Drive account and it would get updated in the application. The key here is that I am ONLY accessing ONE account that I own MYSELF. The users' accounts are not being accessed. Therefore the goal is to never have to log in manually. It should all happen behind the scenes, aka, it should look like a server, not a google doc.
With this in mind, it doesn't make sense to show the Google Accounts sign-in page to my users as the standard OAuth2.0 tutorial shows here:https://developers.google.com/drive/quickstart-ios#step_1_enable_the_drive_api
I should be able to access my own data by somehow hardcoding in my username, password etc. Google agrees here: https://developers.google.com/drive/service-accounts#use_regular_google_accounts_as_application-owned_accounts
The above link mentions a "refresh token" that I'm supposed to save. However, I have no idea how to build and save that token, or even for that matter, where to find it.
I've gone through both the basic tutorial and the Dr. Edit Tutorial for iOS, but they both assume that the application is accessing USER accounts not application-owned accounts.
I'm not asking for someone to write the code for me (though tidbits are nice), but if you can point me to a step-by-step guide or related sample code that would help me get started that would be awesome. I'll even come back and post the code that I use!
EDIT: Since I realized that the Google Drive API wasn't something I could use for what I am trying to do, I eventually found Parse which is an awesome tool that handles all the server backend for me and is free at the basic level.

Google APIs objective-C client library doesn't support service (application-owned) accounts, because they are supposed to be used by a server-side apps, instead of clients -- you shouldn't be distributing your private key as a part of an app.
If you would like to distribute content from a service account, maybe you should write a server leg to do the authentication and pass clients credentials in a secure way for them to talk to the API on the behalf of the service account. Or, use Web publishing to make documents universally accessible without authorization and authentication if privacy is not a concern.

Related

Gmail API OAUTH2 verify Desktop application

At work we have developed an individual customer specific software application that is in use for a long time. We have a new requirement in this same program to implement an option for sending emails directly from the program.
The user is able to add his own email account with the credentials and login through our program. For Microsoft and Gmail accounts OAUTH is implemented and something here is not very clear.
For Gmail-API we have made an OAUTH Client and Consent screen on Google Cloud Console which we need to publish and verify and here is where the problems start. I am not very clear with the whole process of verifying the app.
In the steps for verifying is stated that we should verify a domain for the app, but this software is not hosted anywhere on internet and is not publicly available, it is available to a number of specific users (2000-3000).
Also Google requires a YouTube video of the software to be available publicly, which we are not able to upload because of customer requirements. Also here is required a Data Protection Policy page for the application which we as a developers don't have because we are only developing the software.
Other thing that is not clear to me, how is this type of software rated by Google, internal or public?
Have anyone experience with this or something similar?
Verifying an app for one of the Gmail scopes is a very complicated process. This process depends upon which scope of authorization you are requesting of the users.
In your case you are trying to send an email so you are using the users.messages.send method from the Gmail api. This uses a restricted scope. Which means you will need to go though the full process.
First of it doesn't matter if your application is hosted or not. It also doesn't matter that you give this app to a limited number of users. What matters is the scopes you are using.
You will need to ensure that your domain has been registered via google search console. So this app will need a domain
Once that is done you will be able to host your website, and the privacy policy on that domain.
You will need to create a YouTube video showing your application running, and how authorization is used.
You will also need to submit to a third party security checkup of your application which is not free and will need to be done once a year.
All of this is needed because of your consent screen it doesn't matter if its hosted any where, It also doesn't matter if this is only available to specific number of users.
If all of the users are part of a single google workspace account, that has created your client id and client secrete then you can set the app to internal and you wont need to be verified. This only works for google workspace domain accounts.

Connecting a desktop app to Google Photos without disclosing the app's secret key

I'm writing an open-source stand-alone desktop app in Java that handles photos, and I'm adding a feature to let users upload pictures to their Google Photos account, but I'm faced with an authentication/security question.
I've registered my project to use the Google Photo API and have downloaded my credentials JSON file. I've been able to use it successfully with the samples from the java-photoslibrary Github project, so all is good.
However, the credentials file contains a "client_secret" key which, if I'm not mistaken, should not be disclosed (am I correct here ?). But those credentials have to somehow be distributed with the app and, as it is open-source, will be basically public. So my question is: How can I authenticate my app's user to his/her Google Photo account without disclosing my app's secret key ?
Note: I've integrated Dropbox upload, and their procedure for desktop apps clearly explains how to authenticate without embedding the secret key in the Desktop app using OAuth's token flow. Is there an equivalent for Google Photos ?
Thanks.
Edit: made some progress (see my own answer below), but after I finally got time to implement it, I realized that after user has authorized the app and a valid code has been returned (Yay!), step 5 (Exchanging the code for a token) again requires the client_secret ! :-(
I tried the call without it but I'm receiving a "client_secret is missing" error, so that's not a typo.
After more search (with the [google-oauth] keyword instead of [oauth-2.0], which says it all), it seems "secret" does not mean it is actually "secret" in Google world. In other terms, it's OK to embed it in your apps because, well, it's secret but it cannot be used in a malicious way (hopefully)...
See answers to these related questions:
Safely distribute OAuth 2.0 client_secret in desktop applications in Python
Why does Google provide a client secret for a Native application?
Integrate oauth2 with native (iOS/Android) mobile application
One Google page even mentions that "In this context, the client secret is obviously not treated as a secret."
Come on Google, explain me how security works :-)
OK I think I found the answer.
Similar to Dropbox, Google can use OAuth 2 with PKCE, they just use the full spelling "Proof Key for Code Exchange", that's probably why I didn't find it at first :-). The details are here:
https://developers.google.com/identity/protocols/oauth2/native-app#obtainingaccesstokens
I didn't find the equivalent process in the Google APIs, but those API are megabytes of classes so I may have missed it. Basically, all it takes is just sending a few requests and listening to the response, so I think I'll implement it from scratch (and will probably also get rid of Dropbox's client libs as the process is so similar).
Hope it helps...
Edit: that doesn't address the point because after the clean PKCE procedure, the app still has to send its private key to exchange the authorization code for a token. See edit in my question

how to make an quickbooks Api call and bypass login

I know I'm probably going to get a "no, you can't do that" but it doesn't seem reasonable to me.
My client uses Quickbooks Online and wants to be able to have his customers sign in to his web site and see how much they owe, and then pay their invoices with a credit card.
Obviously, the customers themselves can't be signing into Quickbooks Online. We want the web server to be able to directly access the data via the api.
I've found the api but I'm not sure if it's possible to have the webserver connecting to it and getting the data it needs.
I know this can be done with other systems. I've done it with GMail and Salesforce using OAuth2.
The biggest piece I want to load from quickbooks as well might be something unavailable as I couldn't find it in the API anywhere. When my client opens Quickbooks Online, he can send an email to any customer that will include a link to pay online by credit card. We'd like to be able to find that link and redirect the user to it. But I'm not sure if it's available via the api.
I could go with webhooks but that would require storing all that data on our webserver, and syncing it for existing data. Not to mention what happens if an update happens to fail.
You're misunderstanding how OAuth works a bit, which is what is causing the confusion here.
The person who owns the QuickBooks company logs in, not the end-user. They log in ONCE, and that gets you OAuth tokens that you can use to make server-to-server calls forever going forward.
Soooo...
I know I'm probably going to get a "no, you can't do that" but it doesn't seem reasonable to me.
You can do what you're trying to do, you're just going about it the wrong way.
Obviously, the customers themselves can't be signing into Quickbooks Online.
Correct.
We want the web server to be able to directly access the data via the api.
That's fine, and totally do-able.
I've found the api but I'm not sure if it's possible to have the webserver connecting to it and getting the data it needs.
It is do-able.
The key understanding here is that you're going to have an OAuth connection process that the person who owns QuickBooks is going to go through just once, to get you OAuth tokens.
You're then going to store those OAuth tokens server-side (e.g. in your database).
You can then use those stored OAuth tokens to make future server-to-server API calls whenever you want.
When my client opens Quickbooks Online, he can send an email to any customer that will include a link to pay online by credit card. We'd like to be able to find that link and redirect the user to it. But I'm not sure if it's available via the api.
I don't think this information is available via the API right now.
There is an API endpoint to send an email invoice, if that's helpful:
https://developer.intuit.com/docs/api/accounting/invoice

Linking Google Assistant with Firebase Auth

I am attempting to connect a Google Assistant app using DialogFlow(Api.AI) with Firebase Auth. My App uses Firebase Auth to maintain user accounts and the realtime database to store data. I would like to be able to make changes to a user's data through the Google Assistant, maybe using something like a cloud function. In order to make any user changes through Google Assistant, I need to link the user's Google Assistant account with their Firebase Auth account. The current mechanism appears to be using an OAuth flow documented here.
The question I have is, what is the best way to accomplish this? Do I need to set up a custom OAuth server? There is a lot of documentation on Google's cloud website about OAuth, but it all appears to be related to using OAuth to access Google's APIs, and I can't really see a simple way to host this linking mechanism in GCP.
There is this question that is pretty close, but the difference I have is that I don't have an external API, I just want to authenticate my user and be able to modify their data in the realtime database.
Thank you for your help!
here is an example: https://github.com/malikasinger1/Quiz-Assistant
i have done it myself with following best practices,
feel free to comment if you don't understand something.

how to use GoogleAuthenticator for tfa (two-factor authentication) in a custom non-google login webapp

ok, I've spent 2 hours googling on what it is & how to use it in a web-application! but no success.
Most of the links talk about scanning codes or entering some key in the GoogleAuthenticar mobile app and it'll return changing verification codes every 30 seconds.
Few things :
The webapplication has it's own login. That means users don't login using Google into the webapp.
If an attacker gets the user's password, he sees the QRcode as the next-step, which he can scan directly with the GoogleAuthenticator app in his mobile (as far as it appears to me). How is it tied to user's mobile only ?
In various sites, it mentions a shared secret between user & server, that means at the time of signup, we provide the user the shared-secret, which he can use in her mobile GoogleAuthenticator app and then use it while reading the QR code ?
In the above case, how to proceed if the secret is lost or forgotten by the user ? Use forget secret to send the secret again to user's email ?
I am confused about how can it be implemented in a fashion when it's a non-google non-android application!
All I get is that, it's just a concept asking for our own implementation with some help from the source-code of the GoogleAuthenticator. Please correct me ?
What I think is the solution is that, we have to write our own mobile-app, just like this guy mentioned here, although I'm still not sure how will the secret between the mobile-app and the server will be unique with each installation of that app such that it identifies a particular user only or is there any way to write our own app and use GoogleAuthenticator mobile app without having Google-login in our webapp ?
Google Authenticator (the mobile application) implements the Time-based One-time Password Algorithm. In the scenario you are asking about, two-factor authentication would work as follows:
The user generates a one-time password to be validated by a server application.
The server would verify the password using the procedure detailed by the TOTP algorithm.
The password generation on the user device can be performed by any application implementing TOTP which has been "configured" for your user account. Configured here means having shared a secret with the server, as you mention yourself in the question.
Now, trying to answer your questions:
The fact your application uses its own set of user credentials or Google's has no direct effect on two-factor authentication. No matter what these credentials are, you need a way to identify your user (the username) in order to be able to proceed to the validation of its TOTP password, because you need to know who the user is. Said another way: using TOTP and using the Google Authenticator application does not imply having to use Google credentials on your site.
I'm not sure I understand correctly. The configuration of the Google Authenticator app for each account is performed only once. If an attacker is sitting right behind your back and takes a photo of your screen while you configure Google Authenticator, then yes, he'd be able to configure its own application with your credentials reading the same barcode you're using. Nevertheless, he'd also need your credentials (proper) in order to perform the login and then provide the one-time TOTP password. Anyway, this is a security problem which stems from how the user improperly handles its own credentials and you could be subject to similar problems no matter the technology you use. To make an imperfect metaphor, it's like asking "if the user leaves the pin card with the codes on the table, an attacker sees it and steals a photo of it, could it use them?". Sure, he could.
Yes, reading the barcode is one of the ways you can configure the application and sharing the secret between the client application and the server. You can use other means, such as entering the key manually into the application, but using the QR code is quicker and much less error prone. You won't even need to generate the QR code, because you could use Google's Web APIs as I explained in the blog post you were reading when you asked me to answer this question. In fact, the Java server side library described there uses the Google Web API's and returns you an URL for the user to check out and read its own QR. If you want to build your own QR logic, go on, but there's no compelling reason you should do that if you're eligible to use Google's APIs (which is something you should check anyway).
If the secret is lost it depends on your own policy, if it's your own application. First of all, you should invalidate the old secret immediately upon user notification. Then, you could use the scratch codes you may have given the user upon creation of the TOTP secret to verify his own identity. If he has lost the scratch codes too, you'd probably want to fall back to some other ways to verify his identity such as using some kind of backup information in his account (backup telephone numbers, security questions, etc.). Once the user identity is verified according to your standards, you would issue a new credential and would begin from the start: that is, reconfiguring the Google Authenticator using a new QR and/or a new secret key.
To summarise: yes, you can use the Google Authenticator application as your client front-end if you want to: there's no need to build another one. The only thing which you should into account is that Google Authenticator uses 30-second windows in its TOTP implementation: the server side logic verifying the TOTP password will have to use the same window size (which is, IIRC, the standard value proposed by the TOTP RFC).

Resources