Search code examples
c#google-apigoogle-workspacegoogle-admin-sdk

Google API users.get error 401 Unauthorized


So, im tryng to use users.get from google api and it work fine if i call it directly Oauth 2.0 Client Application but with it after get the token and make the request its necessary to allow on brownse to use it propertly and i can't let this way.

So, i changed to use service accounts. I get the authentication token, i make the request but everytime i get erorr 401 Unauthorized :

System.AggregateException
  HResult=0x80131500
  Message=Um ou mais erros.
  Source=mscorlib
  StackTrace:
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at googleteste.Program.Main(String[] args) in \source\repos\googleteste\googleteste\Program.cs:line 36

Inner Exception 1:
HttpRequestException: O código de status de resposta não indica êxito: 401 (Unauthorized).

I already did domain delegation on scopes .

I create the keys, JSON and P12.

Thanks.

public static async Task<string> GetAccessTokenFromJSONKeyAsync(string jsonKeyFilePath, params string[] scopes)
    {
      using (var stream = new FileStream(jsonKeyFilePath, FileMode.Open, FileAccess.Read))
      {
        return await GoogleCredential
            .FromStream(stream) // Loads key file
            .CreateScoped(scopes) // Gathers scopes requested
            .UnderlyingCredential // Gets the credentials
            .GetAccessTokenForRequestAsync(); // Gets the Access Token
      }
    }
public static string GetAccessTokenFromJSONKey(string jsonKeyFilePath, params string[] scopes)
    {
      return GetAccessTokenFromJSONKeyAsync(jsonKeyFilePath, scopes).Result;
    }
var token = GoogleServiceAccount.GetAccessTokenFromJSONKeyAsync(
            "Keys/wneniac-2744e4a55337.json",
            new[] { "https://www.googleapis.com/auth/admin.directory.user", "https://www.googleapis.com/auth/admin.directory.user.security", "https://www.googleapis.com/auth/contacts", "https://www.googleapis.com/auth/gmail.modify" });

      Console.WriteLine(new HttpClient().GetStringAsync($"https://admin-admin.googleapis.com/admin/directory/v1/users/usertosearch?access_token={token}&domain= ").Result);

Solution

  • In order for your service account to act on behalf of a user on your domain. Your code must demote what the user it is supposed to be impersonating.

    That is what we use the CreateWithUser method for. This user has been configured in my workspace domain to be allowed to access in my case google drive.

    var credential = GoogleCredential.FromFile(PathToServiceAccountKeyFile)
        .CreateWithUser("no-repply@daimto.com")  // delegate to user on workspace.
        .CreateScoped(new[] {DriveService.ScopeConstants.Drive});
    

    Without denoting what user the service account is supposed to be impersonating, the service account cant do anything.