Search code examples
androidgoogle-app-engineauthenticationgoogle-oauth

How to verify Android id token on App Engine backend


my goal is to build simple app engine back end for my android app. Purpose of this back end is just to verify android clients calls ,and provide password which will be used for further https comunication with my servers. So i started ccording to this http://android-developers.blogspot.in/2013/01/verifying-back-end-calls-from-android.html article. Client side looks like:

GoogleAuthUtil.getToken(MainActivityy.this, "[email protected]", "audience:server:client_id:my_Client_ID_for_web_applications.apps.googleusercontent.com");

this method returns token which looks like this:

eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiMWIyZTllNGU2NGE0MmIzM2U3YjMxMDQwNzUyMzIxYmVlMmJkYmEifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiZW1haWwiOiJtYXRvLnBldHJ1bGFrQGdtYWlsLmNvbSIsInZlcmlmaWVkX2VtYWlsIjoidHJ1ZSIsImVtYWlsX3ZlcmlmaWVkIjoidHJ1ZSIsImNpZCI6IjU0ODk4MTY3NzkzMC0xcGxxamF2OWloOGU4MGJ0ZWdpYzg0YmcycjlxN2MwMi5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImF6cCI6IjU0ODk4MTY3NzkzMC0xcGxxamF2OWloOGU4MGJ0ZWdpYzg0YmcycjlxN2MwMi5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImF1ZCI6IjU0ODk4MTY3NzkzMC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImlkIjoiMTE4MTQ0NjEyNDkzMTM1NzYxOTUwIiwic3ViIjoiMTE4MTQ0NjEyNDkzMTM1NzYxOTUwIiwiaWF0IjoxMzY4NzExODk0LCJleHAiOjEzNjg3MTU3OTR9.oN5ncz6MEAZBW8NXDhc4O-Y82C2mma675lbw9ZZA-1bs8zM9FKQG1K97PfNfxJFImiPMY8UYIjhqDIkHpErjaV0KDJpLv8NkmsdADOFjt5eQkFGWf92fufL7QEIkWqLL1fKxG7f8-OR59O5AOAVchdgtqDt4DhEH7oHfAZqf3wU  

and now i want to authentificate this token on backend. So i created new Web Application Project using Google plugin for eclpise. It generates some sample project. To this project i add Checker class from article which i mentioned above. looks like this:

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;

import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;

public class Checker {

private final List mClientIDs;
private final String mAudience;
private final GoogleIdTokenVerifier mVerifier;
private final JsonFactory mJFactory;
private String mProblem = "Verification failed. (Time-out?)";

private  Logger log ;

public Checker(String[] clientIDs, String audience) {
    mClientIDs = Arrays.asList(clientIDs);
    mAudience = audience;
    NetHttpTransport transport = new NetHttpTransport();
    mJFactory = new GsonFactory();
    mVerifier = new GoogleIdTokenVerifier(transport, mJFactory);
   log = Logger.getLogger(Checker.class.getName()); 
   log.severe("CHECKER CRETAED");
}

public GoogleIdToken.Payload check(String tokenString) {
    GoogleIdToken.Payload payload = null;
    log.severe("CHECK START");
    try {
        log.severe("CHECK 1");
        GoogleIdToken token = GoogleIdToken.parse(mJFactory, tokenString);
        log.severe("CHECK 2");
        if (mVerifier.verify(token)) {
            log.severe("CHECK 3");
            GoogleIdToken.Payload tempPayload = token.getPayload();
            log.severe("CHECK4");
            if (!tempPayload.getAudience().equals(mAudience)){
                mProblem = "Audience mismatch";
                log.severe("Audience mismatch");
            }
            else if (!mClientIDs.contains(tempPayload.getIssuee())){
                mProblem = "Client ID mismatch";
                log.severe("Client ID mismatch");
            }
            else{
                payload = tempPayload;
                log.severe(payload.getEmail().toString());
                log.severe("CHECK 5");
            }
        }
    } catch (GeneralSecurityException e) {
        log.severe("Security issue: " + e.getLocalizedMessage());
        mProblem = "Security issue: " + e.getLocalizedMessage();
    } catch (IOException e) {
        log.severe("Network problem: " + e.getLocalizedMessage());
        mProblem = "Network problem: " + e.getLocalizedMessage();
    }
    log.severe("CHECK END");
    return payload;
}

public String problem() {
    return mProblem;
}

}

and now i do something like this to authentify token provided by android client.

String [] clinetidS  = new String [] {"xxxxxxxxxxxxx-plqjav9ih8e80btegic84bg2r9q7c02.apps.googleusercontent.com"};  //Client ID for installed applications
Checker checker = new Checker(clinetidS, "my_project_at_appspot.appspot.com");  
   checker.check("eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiMWIyZTllNGU2NGE0MmIzM2U3YjMxMDQwNzUyMzIxYmVlMmJkYmEifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiZW1haWwiOiJtYXRvLnBldHJ1bGFrQGdtYWlsLmNvbSIsInZlcmlmaWVkX2VtYWlsIjoidHJ1ZSIsImVtYWlsX3ZlcmlmaWVkIjoidHJ1ZSIsImNpZCI6IjU0ODk4MTY3NzkzMC0xcGxxamF2OWloOGU4MGJ0ZWdpYzg0YmcycjlxN2MwMi5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImF6cCI6IjU0ODk4MTY3NzkzMC0xcGxxamF2OWloOGU4MGJ0ZWdpYzg0YmcycjlxN2MwMi5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImF1ZCI6IjU0ODk4MTY3NzkzMC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImlkIjoiMTE4MTQ0NjEyNDkzMTM1NzYxOTUwIiwic3ViIjoiMTE4MTQ0NjEyNDkzMTM1NzYxOTUwIiwiaWF0IjoxMzY4NzExODk0LCJleHAiOjEzNjg3MTU3OTR9.oN5ncz6MEAZBW8NXDhc4O-Y82C2mma675lbw9ZZA-1bs8zM9FKQG1K97PfNfxJFImiPMY8UYIjhqDIkHpErjaV0KDJpLv8NkmsdADOFjt5eQkFGWf92fufL7QEIkWqLL1fKxG7f8-OR59O5AOAVchdgtqDt4DhEH7oHfAZqf3wU");

and now problem is that Checker class never pass this check:

if (mVerifier.verify(token)) 

is there some way how to check android token online?? any ideas?? or where can be problem??


Solution

  • You can always check the token interactively by using curl to look at

    curl https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=<your-id-token-here>

    What's the exception/problem from mVerifier.verify?