Archived Forum Post

Index of archived forum posts

Question:

OAUTH2 Gmail authentication fails

Sep 19 '17 at 10:44

Problem (Authentication failed):

Initially Gmail authentication through Chilkat failed and after analyzing we found that we have to turn ON "allow less secure apps" for the Gmail account to login successfully.

Proposed Solution by Chilkat:

To avoid turning ON "allow less secure apps" in every Gmail account, we followed solution provided at GMail OAuth2 example

Please find the detailed steps we followed and error code below and help us to resolve this:

1) We created a certificate file(.p12).

Through the service account(in developer console) and we have the service account email address as well.

2) I am able to generate accesstoken successfully.

NSString *accessToken = [http G_SvcOauthAccessToken: iss 
    scope: scope subEmail: sub numSec: [NSNumber numberWithInt: numSec] cert: cert];

3) Connecting to "imap.gmail.com mail" server succeeded.

success = [imap Connect: @"imap.gmail.com"];

4) But when I try to authenticate to gmail account using any gmail ID the authentication fails.

success = [imap Login: @"user@gmail.com" password: accessToken];


Answer

This is a very much misunderstood topic, and one that is not clearly explained in any of the Google documentation (as far as I know). My current understanding of the issue is as follows.

There are two types of OAuth2 authentication procedures:

  1. Two-Legged OAuth2
  2. Three-Legged OAuth2

(See the OAuth2 Bible for a good summary. The flows for Two-Legged OAuth1.0a and Three-Legged OAuth1.0a are the same as for OAuth2, except the content of the messages is different.)

Three-Legged OAuth2 requires the owner of the resource (i.e. the owner of the GMail account) to interactively provide authorization to allow the application to access the GMail account. In a web application, this involves a callback to a Google URL to interactively get permission.

If your application is not running in a browser, then this is not possible. (or it is possible in an clunky and awkward way using an embedded or external browser that involves having the GMail account owner paste a URL and then copy/paste a PIN back to the application)

What most people want is this: An application owned by themselves to access a GMail account also owned by themselves. In other words, the application is not trying to access some GMail account owned by some other person. (To put it simply: It's MY GMail account, and it's MY application. Why can't I have MY application access MY GMail account without jumping through hoops as if the GMail account was owned by somebody else???)

This is where two-legged OAuth2 SHOULD solve the problem, but it doesn't. Not for consumer GMail accounts. It is possible with a Google Apps account where the email address is NOT a gmail.com email address.

Two-legged OAuth2 is used with a Service Account. See https://developers.google.com/identity/protocols/OAuth2ServiceAccount To quote the Google documentation:

For this scenario you need a service account, which is an account that belongs to your application instead of to an individual end user. Your application calls Google APIs on behalf of the service account, so users aren't directly involved. ...

Typically, an application uses a service account when the application uses Google APIs to work with its own data rather than a user's data. ...

Google Apps domain administrators can also grant service accounts domain-wide authority to access user data on behalf of users in the domain...

So... to work with your own data, you must have your own Google Apps domain. A consumer GMail account uses the "gmail.com" domain -- which is not your domain. (Gmail.com is Google's domain.) You must have a Google Apps account were GMail is used for an email address at your own domain. (See https://apps.google.com/products/gmail/ )

Assuming you have a Google Apps domain and you are using GMail for an email address at your own domain, then it is possible to do two-legged OAuth2 via a "service account" (see https://developers.google.com/identity/protocols/OAuth2ServiceAccount ) You'll need to create the Google service account and then "Delegating domain-wide authority to the service account.", and then it is possible to do two-legged OAuth2. (But again, not for a consumer GMail account. If the email address ends with ".gmail.com", then it is a consumer GMail account..)


Answer

To send using OAuth2, you would need a Google Apps account. You can't use OAuth2 to send email for a consumer GMail account.
See http://www.example-code.com/csharp/smtp_gmailOAuth2.asp

Also see the instructions for Delegate domain-wide authority to your service account here:
https://developers.google.com/admin-sdk/directory/v1/guides/delegation#create_the_service_account_and_its_credentials


Answer

To sum it up: OAuth2 isn't the solution for our problem. Each of our user has to create a Google Client account and add your application. This won't help us any further, it's even more waaaaaaaaaaayyyy complicated than asking our users to turn on "Allow less secure apps". Right?