Reputation: 644
I am attempting to verify Google ID tokens with a backend server as per:
https://developers.google.com/identity/sign-in/android/backend-auth
The tokens are initially retrieved by an android app, and are then passed to a backend login server via sockets which attempts verification. As things stand, there is an error thrown at runtime within the GoogleIdTokenVerifier code I am importing.
ServerThread.java:
GoogleIdToken idToken = GoogleAuthenticator.authenticateToken(tokenJson.getToken());
GoogleAuthenticator.java:
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.Properties;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.extensions.appengine.http.UrlFetchTransport;
public class GoogleAuthenticator {
public GoogleAuthenticator(){
}
public static Properties prop;
public static GoogleIdToken authenticateToken(String inputToken) throws IOException{
final JacksonFactory jacksonFactory = new JacksonFactory();
prop = new Properties();
prop.load(GoogleAuthenticator.class.getClassLoader().getResourceAsStream("config.properties"));
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(UrlFetchTransport.getDefaultInstance(), jacksonFactory)
// Specify the CLIENT_ID of the app that accesses the backend:
.setAudience(Collections.singletonList(prop.getProperty("google.web.client.id")))
// Or, if multiple clients access the backend:
//.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3))
.build();
GoogleIdToken idToken;
try {
idToken = verifier.verify(inputToken);
return idToken;
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
}
pom.xml
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.25.0</version>
</dependency>
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client-appengine</artifactId>
<version>1.25.0</version>
</dependency>
I am currently seeing the following stack trace:
Exception in thread "Thread-0" java.lang.NoClassDefFoundError: com/google/appengine/api/urlfetch/HTTPMethod
at com.google.api.client.extensions.appengine.http.UrlFetchTransport.buildRequest(UrlFetchTransport.java:118)
at com.google.api.client.extensions.appengine.http.UrlFetchTransport.buildRequest(UrlFetchTransport.java:50)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:872)
at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.refresh(GooglePublicKeysManager.java:172)
at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.getPublicKeys(GooglePublicKeysManager.java:140)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:174)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:192)
at com.omarhegazi.login.GoogleAuthenticator.authenticateToken(GoogleAuthenticator.java:40)
at com.omarhegazi.login.ServerThread.run(ServerThread.java:45)
It looks like there's no HTTPMethod class available amongst the dependencies. Any thoughts?
UPDATE 1:
Adding the appengine dependency below has made some progress. I now have the following stack trace error:
Exception in thread "Thread-0" com.google.apphosting.api.ApiProxy$CallNotFoundException: The API package 'urlfetch' or call 'Fetch()' was not found.
at com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:98)
at com.google.appengine.api.urlfetch.URLFetchServiceImpl.fetch(URLFetchServiceImpl.java:37)
at com.google.api.client.extensions.appengine.http.UrlFetchRequest.execute(UrlFetchRequest.java:74)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:981)
at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.refresh(GooglePublicKeysManager.java:172)
at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.getPublicKeys(GooglePublicKeysManager.java:140)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:174)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:192)
at com.omarhegazi.login.GoogleAuthenticator.authenticateToken(GoogleAuthenticator.java:40)
at com.omarhegazi.login.ServerThread.run(ServerThread.java:45)
This was using v1.6.1
I've also attempted to use v1.9.70 which results in the following:
Exception in thread "Thread-0" com.google.apphosting.api.ApiProxy$CallNotFoundException: Can't make API call urlfetch.Fetch in a thread that is neither the original request thread nor a thread created by ThreadManager
at com.google.apphosting.api.ApiProxy$CallNotFoundException.foreignThread(ApiProxy.java:800)
at com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:112)
at com.google.appengine.api.urlfetch.URLFetchServiceImpl.fetch(URLFetchServiceImpl.java:40)
at com.google.api.client.extensions.appengine.http.UrlFetchRequest.execute(UrlFetchRequest.java:74)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:981)
at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.refresh(GooglePublicKeysManager.java:172)
at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.getPublicKeys(GooglePublicKeysManager.java:140)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:174)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:192)
at com.omarhegazi.login.GoogleAuthenticator.authenticateToken(GoogleAuthenticator.java:40)
at com.omarhegazi.login.ServerThread.run(ServerThread.java:45)
It looks like the fetch package gets included later than 1.6.1, but there's some issues relating to the threads in which the API calls are made.
Upvotes: 2
Views: 1594
Reputation: 644
As per ngueno's post above, I needed appengine-api-1.0-sdk v1.9.70 to get this working:
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-1.0-sdk</artifactId>
<version>1.9.70</version>
</dependency>
To resolve the "Can't make API call urlfetch.Fetch in a thread that is neither the original request thread nor a thread created by ThreadManager" error that was being thrown with this version of the appengine API, I had to change the HttpTransport used from UrlFetchTransport.getDefaultInstance() to GoogleNetHttpTransport.newTrustedTransport()
i.e.:
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
prop = new Properties();
prop.load(GoogleAuthenticator.class.getClassLoader().getResourceAsStream("config.properties"));
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(httpTransport, gsonFactory)
// Specify the CLIENT_ID of the app that accesses the backend:
.setAudience(Collections.singletonList(prop.getProperty("google.client.id")))
.setIssuer("https://accounts.google.com")
// Or, if multiple clients access the backend:
//.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3, etc))
.build();
// (Receive idTokenString by HTTPS POST)
GoogleIdToken idToken;
idToken = verifier.verify(inputToken);
All references and guides used had pointed to the UrlFetchTransport.getDefaultInstance() being Thread safe/the best option to use but it did not work for me here.
Upvotes: 1
Reputation: 2821
Try to include the appengine
dependency in your pom.xml
:
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-1.0-sdk</artifactId>
<version>1.6.1</version> <!-- Check your version -->
</dependency>
Upvotes: 1