0

I used the following example from google https://developers.google.com/identity/sign-in/web/server-side-flow so far I was able to achieve the following steps:

  1. User authenticate on the client side (browser)
  2. Code is returned back and saved on the server db
  3. when asking for an auth code TokenResponseException: 401 Unauthorized.

I checked the following:

  1. API is enabled
  2. over https://developers.google.com/oauthplayground I tested the access with the same client id and client secret and it works
  3. read almost every SO query that was related to this issue but none of them really helped.
  4. tried to revoke all user permissions and re ask them to get a new code.

Below is the code I am using:

public void getUserAuthTokens(String authCode){
    try {

        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
                JacksonFactory.getDefaultInstance(),new FileReader(new ClassPathResource("static\\client_secret.json").getFile()));

        List<String> scopes = new ArrayList<>();
        scopes.add("https://www.googleapis.com/auth/gmail.readonly");
        //String scopes[]={"https://www.googleapis.com/auth/gmail.readonly"};

        Collection<String> SCOPES
                = Collections.unmodifiableCollection(
                Arrays.asList(
                        new String[]{
                                GmailScopes.GMAIL_READONLY
                        }));
        GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(new NetHttpTransport(),JacksonFactory.getDefaultInstance(),
                "https://www.googleapis.com/oauth2/v4/token",
                clientSecrets.getDetails().getClientId(),
                clientSecrets.getDetails().getClientSecret(),
                authCode).setRedirectUri(clientSecrets.getDetails().getRedirectUris().get(0)).setScopes(SCOPES).execute();


        String accessToken = tokenResponse.getAccessToken();
        System.out.print("Token is: "+accessToken);
    }catch (IOException x){
        x.printStackTrace();

    }

}

as a side note, if I didnt use setRedirectUri(clientSecrets.getDetails().getRedirectUris().get(0)) then i got "redirect mismatch error"

I would greatly appreciate any ideas on this as I ran out

user2145673
  • 363
  • 1
  • 9
  • 23

3 Answers3

0

Based from the Standard Error Responses that Google APIs return, an error code 401 Unauthorized indicates a problem with the authorization credentials provided for the request. You may want to check these possible reasons:

  • The OAuth access token has expired and needs to be refreshed. This can be avoided by refreshing the access token early, but code can also catch this error, refresh the token and retry automatically.
  • Multiple non-matching authorizations were provided; choose one mode only.
  • The OAuth access token's bound project does not match the project associated with the provided developer key.
  • The Authorization header was of an unrecognized format or uses an unsupported credential type.

See this documentation for more information regarding the use of OAuth 2.0 to access Google APIs. Suggested solution in this related SO post might also help.

Community
  • 1
  • 1
Teyam
  • 7,686
  • 3
  • 15
  • 22
  • Well I am at the stage where the code is sent to google in order to get the access token and thats where it fails. you can see the relevant code above. the error is caught in the catch block and I can see the error in the stack trace. any ideas what can cause that? – user2145673 Apr 10 '17 at 12:38
0

After much debugging and searching I found a solution that works, I am posting this here in case someone will encounter the same issue.

Here is the code I used:

GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(new NetHttpTransport(),JacksonFactory.getDefaultInstance(),
                "https://www.googleapis.com/oauth2/v4/token",
                clientSecrets.getDetails().getClientId(),
                clientSecrets.getDetails().getClientSecret(),
                authCode, "postmessage")
                .execute();

You can read more on the postmessage @ Google+ Sign-in for server-side apps, exchanging auth code for access token

Hope that helps.

Community
  • 1
  • 1
user2145673
  • 363
  • 1
  • 9
  • 23
0

I eventually discovered that I was seeing "TokenResponseException: 401 Unauthorized" as a result of my data store not updating its credential with a different scope. Like magic, deleting the data store (and clearing session cache) before restarting the test authorization over from the beginning led to success. I don't recommend those steps for every circumstance; however, they may be worth trying as a debug step when all else fails.

b9509746
  • 43
  • 7