Eoghan
Eoghan

Reputation: 1761

Using Google's Java authentication within Scala?

I'm currently attempting to build a GPlay authentication service on a Scala backend. The client is sending through their ID Token and salt; and from here, I'm attempting to use Google's Backend Auth documentation in order to authenticate the user's GPlay account.

As expected, Google's Java libs can all be used without issue with Scala.

Java/Scala imports:

import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;

Java:

GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
    .setAudience(Collections.singletonList(CLIENT_ID))
    .build();

Scala:

val verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
  .setAudience(Collections.singletonList(CLIENT_ID))
  .build();

Their guide seems to be leaving a lot out - namely, what should be instantiated for the transport, jsonFactory, and CLIENT_ID vars. It also does not make any reference as to why the CLIENT_ID should be stored in a singletonList, rather than just a string as we would normally implement on the client.

Currently, I'm getting (as expected), "cannot resolve symbol" errors for transport, jsonFactory, and CLIENT_ID. I've the same error appearing for Collections, but I assume that's because I haven't attempted to create any collection - as no indication is given on the documentation as to what we should be looking to instantiate a collection with.

Any help that could be offered would be greatly appreciated.

Upvotes: 0

Views: 1338

Answers (1)

Pedro Hidalgo
Pedro Hidalgo

Reputation: 869

I took the below code from here: https://developers.google.com/api-client-library/java/google-api-java-client/oauth2

GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Plus plus = new Plus.builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential)
    .setApplicationName("Google-PlusSample/1.0")
    .build();

There you can see an example on how to create the transport and jsonFactory variables you need.

I already created a token validation functionality on Java, In case you need it below is an example:

public static Optional<GoogleIdToken> validateGoogleToken(final String idTokenString) {
        try {
            Optional<String> clientIDConfValueOptional = PlayUtil.getConfValue("GOOGLE_CLIENT_ID");
            if (clientIDConfValueOptional.isPresent()) {

                //PLEASE NOTE!!!!
                //for ANDROID with PlayServices 8.3 + issuer=https://accounts.google.com
                //OTHERWISE issuer=accounts.google.com
                //the otherwise is without "https://"
                GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(
                       MiscUtil.NET_HTTP_TRANSPORT, JacksonFactory.getDefaultInstance())
                        .setAudience(Arrays.asList(clientIDConfValueOptional.get()))
                        // If you retrieved the token on Android using the Play Services 8.3 API 
                        //                        or newer, set
                        // the issuer to "https://accounts.google.com". Otherwise, set the issuer to
                        // "accounts.google.com". If you need to verify tokens from multiple sources, build
                        // a GoogleIdTokenVerifier for each issuer and try them both.
                        .setIssuer("accounts.google.com")
                        .build();

                GoogleIdToken googleIdToken = verifier.verify(idTokenString);
                if (googleIdToken != null) {
                    Payload payload = googleIdToken.getPayload();

                    // Print user identifier
                    String userId = payload.getSubject();
//                    System.out.println("User ID: " + userId);

                    // Get profile information from payload
//                    String email = payload.getEmail();
//                    System.out.println("email = " + email);
//                    boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
//                    System.out.println("emailVerified = " + emailVerified);
//                    String name = (String) payload.get("name");
//                    System.out.println("name = " + name);
//                    String pictureUrl = (String) payload.get("picture");
//                    System.out.println("pictureUrl = " + pictureUrl);
//                    String locale = (String) payload.get("locale");
//                    System.out.println("locale = " + locale);
//                    String familyName = (String) payload.get("family_name");
//                    System.out.println("familyName = " + familyName);
//                    String givenName = (String) payload.get("given_name");
//                    System.out.println("givenName = " + givenName);

                    // Use or store profile information
                    // ...
                    return Optional.ofNullable(googleIdToken);
                } else {
                    System.out.println("Invalid ID token.");
                }
            } else {
                throw new IllegalArgumentException("CLIENT_ID key can't be found on application.conf file");
            }
        } catch (GeneralSecurityException | IOException ex) {
            Logger.error("Error: ", ex);
        }
        return Optional.empty();
    }

You probably know how to translate this code from Java to Scala anyway if you need some help you can use a service like this: java to scala converter

Hope this helps.

Upvotes: 1

Related Questions