43

I am getting the following error when i tried to authorize gmail api using service account

"Client is unauthorized to retrieve access tokens using this method"

static async Task MainAsync()
    {

        sstageEntities db = new sstageEntities();
        //UserCredential credential;
        Dictionary<string, string> dictionary = new Dictionary<string, string>();    
String serviceAccountEmail =
"xxx.iam.gserviceaccount.com";

        var certificate = new X509Certificate2(
            AppDomain.CurrentDomain.BaseDirectory +
              "xxx-8c7a4169631a.p12",
            "notasecret",
            X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);

        //string userEmail = "user@domainhere.com.au";

        ServiceAccountCredential credential = new ServiceAccountCredential(
            new ServiceAccountCredential.Initializer(serviceAccountEmail)
            {
                User = "xxx@xxx.com",
                Scopes = new[] { "https://mail.google.com/" }
            }.FromCertificate(certificate)
        );


        // Create Gmail API service.
        var gmailService = new GmailService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = ApplicationName,
        });

        // Define parameters of request.

        var emailListRequest = gmailService.Users.Messages.List("xxx@xxx.com");
        emailListRequest.LabelIds = "INBOX";
        emailListRequest.IncludeSpamTrash = true;
        emailListRequest.Q = "from:bpm@xxx.co.in is:unread";



        //Get our emails
        var emailListResponse = await emailListRequest.ExecuteAsync();

I am using the p12 key which i got while creating service account.But when i run my console app the following error occurs.Any help would be really appreciated.

Thanks in advance !

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
Melvin
  • 877
  • 3
  • 11
  • 27

4 Answers4

43

The service account needs to be authorized or it cant access the emails for the domain.

"Client is unauthorized to retrieve access tokens using this method"

Means that you have not authorized it properly check Delegating domain-wide authority to the service account

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • Can a normal user access the gmail API through the service account authentication? – Hariprasath Jun 07 '17 at 06:55
  • 15
    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. – Linda Lawton - DaImTo Jun 07 '17 at 06:57
  • 1
    Thanks for the clarification DalmTo. – Hariprasath Jun 07 '17 at 08:26
  • 1
    I get the same error, I set up the correct authorization in G Suite for the service account to access sheets through " https://www.googleapis.com/auth/spreadsheets" but I still get the error, any ideas? – Fabian Bosler May 03 '18 at 12:15
  • @FabianBosler make sure you have the admin of the gsuite account set it up https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority – Linda Lawton - DaImTo May 03 '18 at 12:22
  • I am the admin :D – Fabian Bosler May 03 '18 at 12:48
  • 4
    @DaImTo, I found that sometimes "Delegating domain-wide authority to the service account" take a longer time to take effect. Usually a few seconds, but it can be longer than 5 minutes. Why does this happen? Any suggestion for this problem? Thanks. – skyfree May 26 '18 at 10:05
  • probably something on Google end. I don't have access to gsuite so can't test it myself – Linda Lawton - DaImTo May 26 '18 at 10:38
  • 3
    Important clarification: "Delegating domain-wide authority to the service account" MUST be enabled before you add service account and its scopes on "Manage API client access" page in G Suite Admin. Otherwise it will fail and require re-adding. – Aldekein Nov 27 '19 at 10:01
  • @DalmTo so how are you supposed to authenticate a normal gmail account if you don't have gsuite? I've been trying to get this to work for 2 days now... – boydenhartog May 07 '20 at 18:21
  • 2
    @boydenhartog your not supposed to its not allowed. Normal gmail accounts dont support service accounts. You need to use oauth2 and authenticate your account once and use the refresh token to access it again. – Linda Lawton - DaImTo May 11 '20 at 06:12
  • Facing the issue that:```To change domain wide delegation, a product name for the OAuth consent screen must be configured. You can enter the product name below. On some platforms, the email address is shown with the developer information. To select a different email address, configure consent screen.``` How do I fix that problem, bug report? It's the purpose of the service account to do this access because I donot want to have a consent screen. I donot want to have any user interaction and rely on a chain of refreshed tokens thereafter. – Lenny Jun 18 '20 at 08:11
  • @Lenny have you tried doing what it says and just updating it. Service accounts will not popup with a consent screen. Your just changing the name of the product. – Linda Lawton - DaImTo Jun 18 '20 at 08:13
  • @DaImTo Yhea thank you!! It actually works when configuring the consent screen. Still it's basically broken UX. :D – Lenny Jun 18 '20 at 08:21
  • @Lenny actually i think its more broken user experience vs explanation of the reason for this. – Linda Lawton - DaImTo Jun 18 '20 at 08:26
  • 1
    @DaImTo Yhea, much improvement potential there on Googles' side IMO^^ – Lenny Jun 18 '20 at 08:29
  • Its a free service you get what you pay for . – Linda Lawton - DaImTo Jun 18 '20 at 08:31
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/216188/discussion-between-lenny-and-daimto). – Lenny Jun 18 '20 at 08:35
  • 1
    @Aldekein -- This comment solved my issue. This was the only place I found anything calling out the ordering, and turning everything "off" and then back on again fixed it. – Jessica Larson Jul 22 '20 at 22:54
3

FWIW, since I'm too new to comment, DalmTo and Shane's answers pointed me in the right direction for my problem, which was that new functionality that I had added to an existing script (PHP) needed authorization of additional scopes for the service account. In my case, I'm working with the GMail API.

Besides the path mentioned in the Google documentation page that Shane cited, you can also go to https://admin.google.com/ac/owl/domainwidedelegation, where you can manage domain-wide delegation in a slightly different interface (I actually prefer it). I got to that page via Security > API Permissions, then clicking on the notice about those settings moving to App Access Control, where there's a "Manage Domain Wide Delegation" link at the bottom.

2

In my case authorization was given to an old client id in https://admin.google.com/

After providing the scopes with correct client ID it started to work. (Use the guide link mentioned by DalmTo in above answer.

Anton Perera
  • 353
  • 3
  • 9
2

I had the same issue and it took me a while to realise what I was missing. I had already set Domain-wide authority in the service account setting. However, I had not added the clientid and API scope (e.g https://www.googleapis.com/auth/gmail.send, or https://mail.google.com/) in the Domain security settings, as per the link and screenshot below.

https://developers.google.com/identity/protocols/oauth2/service-account#delegatingauthority

Specifically, these steps: steps I was missing

Shane
  • 187
  • 2
  • 13