0

I am trying to download a user's mailbox using the Email Audit API. I am getting a 403 Forbidden response to this code (the error occurs on the last line, the call to the UploadPublicKey method):

    var certificate = new X509Certificate2(System.Web.HttpRuntime.AppDomainAppPath + "key.p12", "notasecret", X509KeyStorageFlags.Exportable);

    ServiceAccountCredential credential = new ServiceAccountCredential(
       new ServiceAccountCredential.Initializer(serviceAccountEmail)
       {
           Scopes = new[] { "https://apps-apis.google.com/a/feeds/compliance/audit/" }
       }.FromCertificate(certificate));

    credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Wait();
    DebugLabel.Text = credential.Token.AccessToken;

    var requestFactory = new GDataRequestFactory("My App User Agent");
    requestFactory.CustomHeaders.Add(string.Format("Authorization: Bearer {0}", credential.Token.AccessToken));

    AuditService aserv = new AuditService(strOurDomain, "GoogleMailAudit");
    aserv.RequestFactory = requestFactory;
    aserv.UploadPublicKey(strPublicKey);

I have created the service account in the Developers Console and granted the Client ID access to https://apps-apis.google.com/a/feeds/compliance/audit/ in the Admin console.

Seems to me like the account should have all the permissions it needs, yet it doesn't. Any idea what I am missing?

  • Did you do domain wide delegation for your service account? https://developers.google.com/drive/web/delegation . The service account you created needs to be granted access to google apps domain user that you want to access. – SGC Aug 11 '15 at 20:57
  • I went under "Manage API client access" in the Admin console and pasted in my Client Name of the service account (e.g. xxxxxxxxxxxx..apps.googleusercontent.com) and then for API Scopes I put in https://apps-apis.google.com/a/feeds/compliance/audit/ . How do I grant the service account permissions to a domain user though? I am wondering if maybe that is not the correct Scope for the Email Audit API? – Jesse Burant Aug 12 '15 at 21:06
  • https://apps-apis.google.com/a/feeds/compliance/audit/ is the right scope for email audit api. Regarding your question, you need to impersonate the user, where that user will get the access to perform the requests on behalf of service account. when you are making calls, you should specify the user to impersonate. check some examples provided here https://developers.google.com/identity/protocols/OAuth2ServiceAccount – SGC Aug 13 '15 at 15:41
  • Can't I just get an access token for my Super User account on the domain and just use that token to then call the Email Audit API? That would seem to me to be easier than having to grant impersonation privileges to the service account every time I need to download a user's mailbox, no? – Jesse Burant Aug 13 '15 at 16:13
  • Something interesting I have noticed... I tried taking a look at the contents of the Token, via JsonConvert.SerializeObject(credential.Token); and I get this: {"access_token":"yadayadayada","token_type":"Bearer","expires_in":3600,"refresh_token":null,"scope":null,"Issued":"2015-08-17T16:07:02.9104014-05:00"} ... I am wondering why scope here is null when I clearly specified a scope in the new ServiceAccountCredential.Initializer... is that a clue to where the problem is? – Jesse Burant Aug 17 '15 at 21:08

1 Answers1

2

OK, so I gave up on trying to make it work with a service account even though that is what Google's documentation would lead you to believe is the correct way to do it. After emailing Google support, I learned I could just use OAuth2 for the super user account that created the application on the developer's console.

So then I worked on getting an access token for offline access (a refresh token) by following the process outlined here: Youtube API single-user scenario with OAuth (uploading videos) and then taking that refresh token and using it with this code:

public static GOAuth2RequestFactory RefreshAuthenticate(){
OAuth2Parameters parameters = new OAuth2Parameters(){
    RefreshToken = "<YourRefreshToken>",
    AccessToken = "<AnyOfYourPreviousAccessTokens>",
    ClientId = "<YourClientID>",
    ClientSecret = "<YourClientSecret>",
    Scope = "https://apps-apis.google.com/a/feeds/compliance/audit/",
    AccessType = "offline",
    TokenType = "refresh"
};
OAuthUtil.RefreshAccessToken(parameters);
return new GOAuth2RequestFactory(null, "<YourApplicationName>", parameters);
}

which is code from here https://stackoverflow.com/a/23528629/5215904 (Except I changed the second to last line... for whatever reason the code shared did not work until I made that change).

So there I was finally able to get myself an access token that would allow me access to the Email Audit API. From there everything was a breeze once I stopped trying to mess around with a service account.

Community
  • 1
  • 1