Spring Social Google - converting a one-time authorization code into an access token/ refresh token on the server

1.7k views Asked by At

The server receives a one-time authorization code from the mobile app. I need to convert this to a spring-social access token and refresh token and save them on the server DB for later usage.

My current code:

String oneTimeAuthorizationCode= "xxx"; // provided by mobile client

ConnectionData cd = new ConnectionData("google", null, null, null, null, oneTimeAuthorizationCode, null, null, null);
GoogleConnectionFactory googleConnectionFactory = (GoogleConnectionFactory) connectionFactoryLocator.getConnectionFactory("google");
Connection<Google> connection = googleConnectionFactory.createConnection(cd);

// get the google API and work with it
Google  google = (Google) connection.getApi();

oneTimeAuthorizationCode is wrong since the ConnectionData is expecting an access token and not the one time authorization code. Any idea how to get spring-social-google to exchange the one-time code for an access token and refresh token?

3

There are 3 answers

0
Ruby Kannan On BEST ANSWER

This is the code to exchange authorization code for access token

String authorizationcode=*****;
auth2Operations = googleConnectionFactory.getOAuthOperations();
AccessGrant accessGrant =auth2Operations.exchangeForAccess(authorizationcode,"Your      redirect uri",null);
connection = googleConnectionFactory.createConnection(accessGrant);
Google google=connection.getApi();
0
Erich On

To get it going your going to need to request offline access for Google. Mostly the change is just adding the query parameter 'access_type=offline' to however you got that oneTimeAuthorizationCode. Then you'll get a refresh token back after authorization.

For my own project, I ended up customizing ProviderSignInController to add the query param manually since it doesn't allow you to pass it in through REST:

@RequestMapping(value="/{providerId}", method=RequestMethod.POST)
public RedirectView signIn(@PathVariable String providerId, NativeWebRequest request) {
    ConnectionFactory<?> connectionFactory = connectionFactoryLocator.getConnectionFactory(providerId);
    MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>(); 
    preSignIn(connectionFactory, parameters, request);

    // Request offline access for Google+. Will allow a refreshToken
    parameters.put("access_type", Arrays.asList("offline"));

    try {
        return new RedirectView(connectSupport.buildOAuthUrl(connectionFactory, request, parameters));
    } catch (Exception e) {
        logger.error("Exception while building authorization URL: ", e);
        return redirect(URIBuilder.fromUri(signInUrl).queryParam("error", "provider").build().toString());
    }
}
0
Hamdy Ben Salah On

The solution:

        GoogleConnectionFactory connectionFactory = new GoogleConnectionFactory("clientId","clientSecret");

        OAuth2Operations oauthOperations = connectionFactory.getOAuthOperations();

        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();

        parameters.put("grant_type", Arrays.asList("authorization_code"));

        //"authCodeFromAndroid" to be replaced by the authCode sent from Android, and exactly returned from the method "getServerAuthCode()"
        AccessGrant accessGrant = oauthOperations.exchangeForAccess("authCodeFromAndroid", "", parameters);

        Connection<Google> connection = googleConnectionFactory.createConnection(accessGrant);

        //Then you can continue with the ordinary "connection" as usual
        String providerId = connection.getKey().getProviderId();
        String providerUserId = connection.getKey().getProviderUserId();