tl dr; give me repo? Yes siiir π
β Previously on "Lost"...
Last time we created server side app with Firebase Authentication, we did some amazing designs for app and also implemented iOS version of our Xamarin app that will use Firebase Authorization and Google as Auth provider. Only Android is missing...
Okaaay Let's go
So we're here! π This is how our main page looks like.
IGoogleAuth for π€
If we'll click on the button obviously it will... crash, because we haven't implemented IGoogleAuth interface from previous post for Android.
public interface IGoogleAuth
{
OAuth2Authenticator Auth { get; }
event EventHandler<AuthenticatorCompletedEventArgs> AuthSuccess;
event EventHandler<AuthenticatorCompletedEventArgs> AuthFailure;
void LoginAsync();
}
First of all you need to add Xamarin.Auth NuGet package to our Android project. Just like on the iOS π
Next... Create new class called GoogleAuth.cs that implements mentioned above interface in the Android project.
using Android.Content;
using System;
using Xamarin.Auth;
namespace GC.SgnlR.Droid
{
internal class GoogleAuth : IGoogleAuth
{
public OAuth2Authenticator Auth { get; private set; }
public event EventHandler<AuthenticatorCompletedEventArgs> AuthSuccess;
public event EventHandler<AuthenticatorCompletedEventArgs> AuthFailure;
public void LoginAsync()
{
Auth = new OAuth2Authenticator(
clientId: "Put_ClientId_Here",
clientSecret: "",
scope: "profile",
authorizeUrl: new Uri("https://accounts.google.com/o/oauth2/v2/auth"),
redirectUrl: new Uri("Put_RedireceUrl_Here"),
accessTokenUrl: new Uri("https://www.googleapis.com/oauth2/v4/token"),
isUsingNativeUI: true);
Auth.Completed += Auth_Complted;
var activity = Xamarin.Essentials.Platform.CurrentActivity;
Intent ui_object = Auth.GetUI(activity);
activity.StartActivity(ui_object);
}
private void Auth_Complted(object sender, AuthenticatorCompletedEventArgs e)
{
if (e.IsAuthenticated)
{
AuthSuccess?.Invoke(this, e);
}
else
{
AuthFailure?.Invoke(this, e);
}
}
}
}
Looks familiar? This is almost the same as iOS but we have Intend and activity instead of RootViewController. What is Intent? Click here!
How do I get ClientId and RedirectId? See my previous post here!
For this moment you can use the same values from GoogleService-Info.plist
Ok let's try it!
Again as on iOS, after successful login we're stuck at Google's page. As you probably figured our we need to consume redirect URL. For that we need separated Android Activity.
If you're curious what's Activity Intent Filter π€ you can check it out here! I think that "REVERSED_CLIENT_ID" is self-explanatory π.
This Activity basically will catch redirect Url and pass it's data to our OAuth2Authenticator object in GoogleAuth class.
Right now we have to handle how to close Web browser in our app. I figured out this solution:
You can dig into topic here:
Right now login should work like charm! π We should be able to open Web view in app, login using our Google Account and be redirected back to the app.
I'm very happy with the outcome, we created consisted Interface for Google's login both for iOS and Android π
IFirebaseService
Back in the day, we introduced this interface
using System.Threading.Tasks;
namespace GC.SignalR
{
public interface IFirebaseService
{
Task<string> LoginWithCredentials(string idToken, string accessToken);
}
}
This interface as has one purpose:
Exchange Google's IdToken and AccessToken for Firebase IdToken.
Firebase Init
To implement mentioned interface we have to add our app in Firebase Console and initialize it inside Android MainActivity. Β So let's log to our Firebase -> Click plus icon and select Android -> fill all needed info.
Download google-services.json file and put it into Android project.
Next Add Xamarin.Firebase.Auth NuGet to the same project.
After adding this NuGet please Init Firebase in OnCreate method in your MainAcitvity
As you can see, we also registered FirebaseService.
IFirebaseService for π€
Now it's time to write some implementations
internal class FirebaseService : IFirebaseService
{
public async Task<string> LoginWithCredentials(string idToken, string accessToken)
{
var authCredential = GoogleAuthProvider.GetCredential(idToken, accessToken);
var auth = await FirebaseAuth.Instance.SignInWithCredentialAsync(authCredential);
var result = await auth.User.GetIdToken(true).ToAwaitableTask();
return (result as GetTokenResult)?.Token;
}
}
I'm using here some Extension Method ToAwaitableTask() that I found useful while working with Android.Gms.Task. Here you can see code and blog post! You can also find it in my repo. π
There is build-in Extension method AsAsync<TResult>()!
Testing
Lucky for us, navigation and messaging page is ready (this is beauty of cross platform developmentβ¨). So there is nothing left for development. Let's find out if it's working!
Launch Server -> Login -> Type message -> Press Send β‘
Outcome:
Conclusion
Developing consistent abstraction for Firebase Auth using Google is not easy cake but it can be done. For sure there are plenty of other possible solutions but maybe you'll get inspired... Who knows π. Regarding this Part I'm very surprised that there was no ambush bug π± (as it was for iOS).
Final words
If you enjoyed this blog post, don't hesitate and Subscribe! I'll publish every 1-2 weeks about Xamarin, .NET and mobile development, if you're interested give it a try! (I won't spam or sell your e-mail π )
Cheers! πΉ