I am trying to use Firebase in Unity(after unsuccessfully trying to get MSAL for Android working within Unity for B2C. Currently, Firebase lets me do a regular email + password register and log in. But when I try to use the Microsoft sign-in feature the app just flashes for a second, my debugger gets detached, and then nothing happens. Any ideas what could be going wrong?
public void SignInWithMicrosoft()
{
StartCoroutine(SignInWithMicrosoftAsync());
}
private IEnumerator SignInWithMicrosoftAsync()
{
var signInTask = auth.SignInWithProviderAsync(provider);
yield return new WaitUntil(() => signInTask.IsCompleted);
if (signInTask.Exception != null)
{
Debug.LogError("SignInWithProviderAsync encountered an error: " +
signInTask.Exception);
}
else
{
AuthResult authResult = signInTask.Result;
FirebaseUser user = authResult.User;
Debug.LogFormat("User signed in successfully: {0} ({1})",
user.DisplayName, user.UserId);
}
}
Tried stripping the provider data down to the bare minimum, and checked to make sure provider contents were valid. I expect it to open a browser(as it states on the Firebase docs) with the Microsoft sign-in.
Solved it(but also went back to Azure B2C) For those that might be looking into this kind of thing in the future here's the Firebase issue I had and also how to do stuff with B2C in Android:
Firebase: My issue was I had to add the SHA-1 and SHA-256 to the firebase console, and also I had forgotten to enable microsoft sign in in the console(so I was just being silly). After that it was opening but I got an error after logging in, didn't go any further than that sorry
Azure B2C: This one was a bit more convoluted. Things you'd have to do:
enable customsettings template to pass in the repository(this is in settingsTemplate)
maven {
url 'https://pkgs.dev.azure.com/MicrosoftDeviceSDK/DuoSDK-Public/_packaging/Duo-SDK-Feed/maven/v1'
}4
enable custom main template to pass in the dependencies needed
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.microsoft.identity.client:msal:4.9.+'
**DEPS**}
enable custom android manifest(this breaks patch and run for me currently
<activity android:name="com.microsoft.identity.client.BrowserTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Add in your scheme/host from registered redirect URI -->
<data android:scheme="msauth"
android:host="com.companyName.appName"
android:path="this is the SHA or smth from keystore="/>
</intent-filter>
</activity>
you'll then have to do a bunch of JNI stuff to interface with it(its a bit annoying, but it'll look something like this in the end:
public class MSALAndroid
{
public AndroidJavaObject publicClientApplication;
public string accessToken;
public TaskCompletionSource<string> tcs;
public MSALAndroid(string clientId, string authority, string redirectUri)
{
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
using (AndroidJavaObject applicationContext = currentActivity.Call<AndroidJavaObject>("getApplicationContext"))
using (AndroidJavaClass publicClientApplicationClass = new AndroidJavaClass("com.microsoft.identity.client.PublicClientApplication"))
{
publicClientApplicationClass.CallStatic("create",
applicationContext,
clientId,
authority,
redirectUri,
new MSALApplicationCreatedListener(this));
}
}
public Task<string> AcquireToken(string[] scopes)
{
tcs = new TaskCompletionSource<string>();
try
{
using (AndroidJavaObject scopeArray = new AndroidJavaObject("java.util.ArrayList"))
{
foreach (string scope in scopes)
{
scopeArray.Call<bool>("add", scope);
}
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
{
object[] parameters = new object[3];
parameters[0] = currentActivity;
parameters[1] = scopes;
parameters[2] = new MSALCallback(this);
publicClientApplication.Call("acquireToken", parameters);
}
}
}
catch (Exception ex)
{
Debug.Log("Error: " + ex.Message);
}
return tcs.Task;
}
}
public class MSALCallback : AndroidJavaProxy
{
private MSALAndroid msalAndroid;
public MSALCallback(MSALAndroid msalAndroid) : base("com.microsoft.identity.client.AuthenticationCallback")
{
this.msalAndroid = msalAndroid;
}
public void onSuccess(AndroidJavaObject authenticationResult)
{
// Handle successful authentication.
// You can call authenticationResult.Call<string>("getAccessToken") to get the access token.
msalAndroid.accessToken = authenticationResult.Call<string>("getAccessToken");
Debug.Log("ACCESS TOKEN: " + msalAndroid.accessToken);
msalAndroid.tcs.SetResult(msalAndroid.accessToken);
}
public void onError(AndroidJavaObject msalException)
{
var exception = msalException.Call<string>("getMessage");
Debug.Log(exception);
// Handle error.
}
public void onCancel()
{
// Handle cancellation.
}
}
public class MSALApplicationCreatedListener : AndroidJavaProxy
{
private MSALAndroid msalAndroid;
public MSALApplicationCreatedListener(MSALAndroid msalAndroid) : base("com.microsoft.identity.client.IPublicClientApplication$ApplicationCreatedListener")
{
this.msalAndroid = msalAndroid;
}
public void onCreated(AndroidJavaObject application)
{
// Handle successful creation here.
msalAndroid.publicClientApplication = application;
Debug.Log("Application created!");
}
public void onError(AndroidJavaObject exception)
{
// Handle error here.
}
}
this code hasn't been tidied up and probably can be improved, but just wanted it out there since I suffered way too much for it