TokenResponseException: 401 Unauthorized Exception when trying to access Admin SDK Google API.

人走茶凉 提交于 2019-12-04 06:42:22

问题


I am trying to do an extract of users in my domain by accessing the Google Admin SDK API. I am however given a 401 unauthorized exception. The code below is my settings class that contains my method to call the API.

 package com.brookfieldres.operations;

   import java.io.File;
   import java.io.IOException;
   import java.security.GeneralSecurityException;
   import java.util.ArrayList;
   import java.util.ResourceBundle;

   import org.apache.log4j.Logger;

   import com.brookfieldres.common.Constants;
   import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
   import com.google.api.client.googleapis.auth.oauth2.GoogleCredential.Builder;
   import com.google.api.services.admin.directory.Directory;
   import com.google.api.services.admin.directory.DirectoryScopes;

    public class GCAuthentication {

        private static final Logger _Log =      Logger.getLogger(GCAuthentication.class.getName()); 

    static ResourceBundle resources =  ResourceBundle.getBundle("Resources"); 

//  public static String serviceAcc = resources.getString("SERVICE_ACC_EMAIL"); 
//  public static String privKeyPath = resources.getString("PRIVATE_KEY_PATH"); 
//  public static String userEmail = resources.getString("ADMIN_ACC"); 



    public static Directory getDirectoryService(String serviceAcc, String privKeyPath, String userEmail) throws IOException, GeneralSecurityException, NullPointerException {

    //  final ArrayList<String> dirScopes = new ArrayList<String>(); 
    //      dirScopes.add(DirectoryScopes.ADMIN_DIRECTORY_USER); 


        Constants.dirScopes = new ArrayList<String>(); 
        Constants.dirScopes.add(DirectoryScopes.ADMIN_DIRECTORY_USER); 
        Constants.dirScopes.add(DirectoryScopes.ADMIN_DIRECTORY_CUSTOMER); 
        Constants.dirScopes.add(DirectoryScopes.ADMIN_DIRECTORY_ORGUNIT);

        GoogleCredential gCreds = new GoogleCredential.Builder()
        .setJsonFactory(Constants.JSON_FACTORY)
        .setTransport(Constants.HTTP_TRANSPORT)
        .setServiceAccountId(serviceAcc)
        .setServiceAccountUser(userEmail)
        .setServiceAccountPrivateKeyFromP12File(new File(privKeyPath))
        .setServiceAccountScopes(Constants.dirScopes)
        .build(); 

        Directory directory = new Directory.Builder(Constants.HTTP_TRANSPORT, Constants.JSON_FACTORY, gCreds).setApplicationName(Constants.APPLICATION_NAME).build(); 

        return directory; 

    }


}

The code below is my test case that i am using to pull users from my domain:

package com.brookfieldres.library.test;

import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertFalse;

import java.io.IOException;
import java.security.GeneralSecurityException;
import org.junit.After;

import com.brookfieldres.operations.GCAuthentication;
import com.google.api.client.repackaged.com.google.common.base.Strings;
import com.google.api.services.admin.directory.Directory;
import com.google.api.services.admin.directory.model.Customer;
import com.google.api.services.admin.directory.model.User;

public class ExtractionTest { 

@Before 
    public void setUp(){}

@Test
    public void getEmails() throws IOException, NullPointerException, GeneralSecurityException{ 

        try {

            Directory directory = GCAuthentication.getDirectoryService("XXXXXXX", "XXXXXXXX", "XXXXXXX"); 
            System.out.println("The connection to Google is established"); 
            User user1 = directory.users().get("XXXXXXXX@XXXX.ca").execute(); 
            System.out.println("User is pulled."); 

    //      assertFalse(user1 == null); 

    //      if(user1 != null){ 
    //          System.out.println("Name= " + user1.getName());
    //      }

        }catch(NullPointerException e) { 
            e.printStackTrace();
        }catch (IOException e){ 
            e.printStackTrace();
        }catch (GeneralSecurityException e) { 
            e.printStackTrace();
        }


    }

@After
    public void tearDown(){ }

}

and Finally here is the exception that i am faced with.

The connection to Google is established
com.google.api.client.auth.oauth2.TokenResponseException: 401 Unauthorized
    at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
    at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
    at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
    at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:384)
    at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489)
    at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:217)
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:868)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
    at com.brookfieldres.library.test.ExtractionTest.getEmails(ExtractionTest.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Any help would be gladly appreciated!!!


回答1:


Based from this thread, TokenResponseException: 401 Unauthorized occurs when having an invalid client ID, client secret or scopes. But it could also be due to refresh token overuse. Refresh the access token, if necessary since it have limited lifetimes. If your application needs access to a Google API beyond the lifetime of a single access token, it can obtain a refresh token. A refresh token allows your application to obtain new access tokens.

Check these related threads:

  • Java Google Contacts API Access Service Account Authentication which states that another possible source for a "401 Unauthorized" exception is leaving the credential.refreshToken() away. The call is necessary to write the access-code into the reference.
  • Always get TokenResponseException: 401 Unauthorized.

Hope this helps!




回答2:


In my case in Intellij IDE, it cashed the credential file which was the issue. So if you are changing the google account and credential file you must also delete the cashed credentials. It is located in your project directory under token/StoredCredential




回答3:


try deleting .credential directory - which is created in your local machine. this works.



来源:https://stackoverflow.com/questions/38834654/tokenresponseexception-401-unauthorized-exception-when-trying-to-access-admin-s

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!