Home Features Docs Blog Support GitHub

MOE Authentication or Native


(Dave Kittredge) #1

Hello,
I am new to MOE. I have not seen any documents / examples, etc. about how to authenticate a cross platform app. I have been able to access SQLite from both Android and IOS. I set up a Google Sign in for Android which gives me a token I can validate on my web services. I do not know how to implement a similar login / token validation for IOS. Do I do this natively (I believe IOS does thumb print or iTunes PW), but I am not sure if I write the code in Java, and if there is possibly an example I could view would be helpful.

Sorry if this is a duplicate post, I have not seen anything on the web about authentication (and MOE).
Thanks!


#2

Bump. I’m exactly in the same boat. Hope someone can provide with some answer.


(Eugene) #3

It all depends. If there is a plain Java library, you can use MOE to run that code from ios app.

Otherwise you can call an ios specific code from moe, e.g. integrate corresponding cocoapod described here https://developers.google.com/identity/sign-in/ios/start-integrating

In a second case it may help to have your own abstraction or interface to hide platform specific implementation behind.


(Juan Irungaray) #4

Take a look at Google’s Firebase , It solves auth for android, ios and web and AFAIK it’s MOE compatible.


(Dave Kittredge) #5

Thanks everyone for your replies. I am sorry to be so novice at this. I have struggled over the past few weeks attempting to add both GoogleSignIn and FireBase to my iOS app.

I have started over, and now find this:
When I add
pod ‘Firebase/Core’
pod ‘Firebase/Auth’
to my Podfile, and run
pod update

I see the Firebase (in this case) pods are added.

If I immediately go to my AndroidStudio project and click the Run IOS button, I get errors:

ld: warning: directory not found for option ‘-L/Users/…/ios/build/moe/xcodebuild/sym/Debug-iphonesimulator/GTMSessionFetcher’
ld: warning: directory not found for option ‘-L/Users/…/ios/build/moe/xcodebuild/sym/Debug-iphonesimulator/GoogleToolboxForMac’
ld: warning: directory not found for option ‘-L/Users/…/ios/build/moe/xcodebuild/sym/Debug-iphonesimulator/nanopb’
ld: warning: -pagezero_size not page aligned, rounding down
ld: library not found for -lGTMSessionFetcher
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I cannot seem to get past these errors even if I remove the Firebase pods from my PodFile (and update). I have only been successful recompiling (the AndroidStudio piece) if I revert back to my trunk version in subversion. BTW, the Xcode project compiles and runs after running the Pod update.

Does anyone have a step-by-step to add either Firebase or GoogleSignin to their IOS app?

Do I:

  • Add the Pods
  • Generate Bindings for the Pods (How to do this?)

Or, do I follow the Google Documentation on adding Firebase to my IOS Project (https://firebase.google.com/docs/ios/setup)

The 2nd step has not worked for me.

Thanks a lot for looking at this!


(Roland Vigh - Migeran) #6

Hi!

Generate binding for the pods:

  • Right click project
  • Multi-OS Engine Actions -> Create New Binding

Sample .nbc file is located firebase and firebase-auth project:

Best Regards:
Roland


(Dave Kittredge) #7

Thank you!

It turns out I was still getting the errors after generating the bindings:

ld: warning: directory not found for option '-L/Users/…/ios/build/moe/xcodebuild/sym/Debug-iphonesimulator/GTMSessionFetcher’
ld: warning: directory not found for option '-L/Users/…/ios/build/moe/xcodebuild/sym/Debug-iphonesimulator/GoogleToolboxForMac’
ld: warning: directory not found for option '-L/Users/…/ios/build/moe/xcodebuild/sym/Debug-iphonesimulator/nanopb’
ld: warning: -pagezero_size not page aligned, rounding down
ld: library not found for -lGTMSessionFetcher
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I found the fix!
adding a line to my iOS build.gradle -> moe -> xcode

workspace ‘xcode/projectName.xcworkspace’ // Workspace is needed when Pods was included in project

Thanks again for your help!


(Dave Kittredge) #8

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;
}

}