After weeks I now have an authentication solution.
Some notes: ignore "MUtils.method() + " in logs, it just returns the method name.
This might help others who try to tackle this beast. In ViewController.java:
@Override
public void viewDidLoad() {
Log.d(LOG_TAG, MUtils.method() + " begin" );
super.viewDidLoad();
FIRApp firApp = FIRApp.alloc().init();
firApp.configure();
gidSignIn = GIDSignIn.sharedInstance();
Log.d(LOG_TAG, MUtils.method() + "===================================================================gidSignIn=" + gidSignIn);
Log.d(LOG_TAG, MUtils.method() + "===================================================================firApp=" + firApp);
gidSignIn.setClientID(CLIENT_ID);
gidSignIn.setDelegate(this);
gidSignIn.setUiDelegate(this);
gidSignIn.signInSilently();
Log.d(LOG_TAG, MUtils.method() + "viewDidLoad end" );
}
After the silent signIn, the app then calls (still in ViewController.java):
@Generated
@Selector("signIn:didSignInForUser:withError:")
public void signInDidSignInForUserWithError(GIDSignIn signIn, GIDGoogleUser user, NSError error){
if (error != null) {
Log.e(LOG_TAG, MUtils.method() + "Error signing in: " + error);
} else {
GIDAuthentication authentication = user.authentication();
Log.d(LOG_TAG, MUtils.method() + "Converting Google token to Firebase ");
FIRAuthCredential credential = FIRGoogleAuthProvider.credentialWithIDTokenAccessToken(authentication.idToken(), authentication.accessToken());
Log.d(LOG_TAG, MUtils.method() + "credential=" + credential);
FIRAuth.auth().signInAndRetrieveDataWithCredentialCompletion(credential, new FIRAuth.Block_signInAndRetrieveDataWithCredentialCompletion() {
@Override
public void call_signInAndRetrieveDataWithCredentialCompletion(FIRAuthDataResult user, NSError error) {
Log.d(LOG_TAG, MUtils.method() + "user=" + user);
Log.d(LOG_TAG, MUtils.method() + "user.additionalUserInfo()=" + user.additionalUserInfo());
Log.d(LOG_TAG, MUtils.method() + "user.user().refreshToken()=" + user.user().refreshToken());
Log.d(LOG_TAG, MUtils.method() + "user.additionalUserInfo().profile()=" + user.additionalUserInfo().profile());
FIRUser currentUser = FIRAuth.auth().currentUser();
currentUser.getIDTokenForcingRefreshCompletion(true, (idToken, nsError) -> {
Log.d(LOG_TAG, MUtils.method() + "idToken=" + idToken);
oneTimeToken = idToken;
// Have new Firebase token!!
loginWebService.verifyToken(oneTimeToken);
});
}
});
Log.d(LOG_TAG, MUtils.method() + "done converting google token to firebase");
}
updateButtons();
}
On the server-side, verifyToken Web Service calls TokenUtils to validateToken:
public class TokenUtils {
private boolean isConnected = false;
/** connect my server to Firebase, only call once
* @throws Exception **/
public static void connect() throws Exception {
if( isConnected ) {
return;
}
FileInputStream serviceAccount = new FileInputStream(JSON_PATH);
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.build();
LOG.info(MUtils.method() + "options=" + options);
FirebaseApp.initializeApp(options);
isConnected = true;
}
public static InternalToken validateToken( String idToken ) {
InternalToken token = new InternalToken();
try {
connect();
FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdTokenAsync(idToken).get();
String uid = decodedToken.getUid();
token.setAccessToken(uid);
LOG.info(MUtils.method() + "uid=" + uid);
} catch (Exception e) {
LOG.error(MUtils.method() + "getGoogleToken One time NOT found, ",e );
}
return token;
}
}