Search code examples
authenticationoauth-2.0oauthgoogle-oauthgmail-api

Getting A Refresh Token From Google Using An Authorization Token Posted in Java


I have read many posts, all the Google documentation I can find and tried many iterations of the following and still can't get an access and refresh token. I do get an authorization code but can't seem to get that to trade for the access and refresh tokens.

            if(authCode == null || authCode.equals("")) {
            String url = "https://accounts.google.com/o/oauth2/v2/auth?"
                    + "scope=https://mail.google.com/&"
                    + "response_type=code&"
                    + "redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&"
                    + "client_id=" + clientId +
                    "&access_type=offline";
            URI uri = new URI(url);
            logger.debug("URI for auth is: "  + uri);
            
            if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
                Desktop.getDesktop().browse(uri);
            }
        }
        
        else {
            logger.debug("Refreshing");
            initRefreshToken();
        }

With that, I get an access code I can cut and paste (just testing and trying to get this to work first) in my properties to get the refresh and access token.

In the initRefreshToken() method, the source is like this:

        if(refreshToken.equals("")) {
        logger.debug("Getting refresh token");
        HttpPost post = new HttpPost("https://oauth2.googleapis.com/token");

        // add request parameter, form parameters
        List<NameValuePair> urlParameters = new ArrayList<>();
        urlParameters.add(new BasicNameValuePair("code", authCode));
        urlParameters.add(new BasicNameValuePair("client_id", clientId));
        urlParameters.add(new BasicNameValuePair("client_secret", clientSecret));
        urlParameters.add(new BasicNameValuePair("redirect_uri", "http://localhost:8000/"));
        urlParameters.add(new BasicNameValuePair("grant_type", "authorization_code"));

        try {
             post.setEntity(new UrlEncodedFormEntity(urlParameters));
             
             System.out.println("***** URL: " + urlParameters);
             CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse response = httpClient.execute(post);

            System.out.println(EntityUtils.toString(response.getEntity()));
        
        }

If this is a second or subsequent time using the code, what will be printed is:

Refersh token: ***** URL: [code=4/1AY0e-g..., client_id=370...i1h2u1s.apps.googleusercontent.com, client_secret=bAOH..., redirect_uri=https://localhost:8000/, grant_type=authorization_code]

{ "error": "invalid_grant", "error_description": "Bad Request" }

If the code is run and it's the first time using an authentication code, it will print:

{ "error": "redirect_uri_mismatch", "error_description": "Bad Request" }

I read in the Google console that exceptions are made for localhost domains so there's no need to register them. However, if there were a need to register them, it won't let you register them anyway as a domain must be a top level domain you own in order to register it. Therefore, how do I register localhost and/or exchange an authorization code for an access and refresh token in Java?

Thank you for your help.


Solution

  • DaImTo provided a great video about this and in that video and the blog post associated with it, the redirect_uri is listed correctly as: "urn:ietf:wg:oauth:2.0:oob". I didn't find this in the documentation but when I added it to my source code, I got access and refresh tokens as a response. Thank you very much for that help, DaImTo.