Well, after a lot of struggling with it I finally managed to get this Firebase Auth thing working on Xojo… sort of. It feels clunky and awkward, or I’m just being too demanding of myself.
In order for it to work I had to first understand that the login widget should not be handled by Xojo. There is an awful lot of javascript to it so it is best to let it sit on a standalone webpage just as shown on the youtube videos above (first post).
As my need is to have an authentication method, I only have to deal with the second part, the “firebase.auth().onAuthStateChanged” part.
This is how I did it:
1 - Created a WebControlWrapper with the following objects:
Constants:
Public Const a_Logout as String = function logOut(){
firebase.auth().signOut();
}
Public Const Firebase_Action as String = firebase.auth().onAuthStateChanged(function(user) {
var res = [];
var myuser = document.getElementById("user");
var mynome = document.getElementById("nome");
if (user) {
// User is signed in.
uid = user.uid;
dname = user.displayName;
myuser.innerHTML = uid;
mynome.innerHTML = dname;
document.cookie = "user=" + uid;
document.cookie = "nome=" + dname;
res.push(uid);
res.push(dname);
Xojo.triggerServerEvent('<<Controle>>', 'Logado', res);
} else {
uid = null;
dname = null;
myuser.innerHTML = "-";
mynome.innerHTML = "-";
document.cookie = "user=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
document.cookie = "nome=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
var d = new Date();
res.push("deslogado");
res.push(d);
Xojo.triggerServerEvent('<<Controle>>', 'Deslogado', res);
}
});
Public Const Firebase_Init as String = <script src="https://www.gstatic.com/firebasejs/5.8.0/firebase.js"></script>
Public Const Firebase_Main as String = // Initialize Firebase
var config = {
apiKey: "YOURFIREBASEAPI",
authDomain: "YOURFIREBASEDOMAIN",
databaseURL: "YOURFIREBASEDATABASEURL",
projectId: "YOURPROJECTID",
storageBucket: "YOURSTORAGEBUCKET",
messagingSenderId: "YOURMESSAGESENDERID"
};
firebase.initializeApp(config);
Public Const JavascriptNamespace as String = lbmdata_firebaseui
Event Definitions:
Event Deslogado(dado As Variant)
Event Logado(dado As Variant)
Event Handlers:
Sub SetupCSS(ByRef Styles() as WebControlCSS) Handles SetupCSS
Styles(0).Value("visibility") = "visible"
End Sub
Function SetupHTML() Handles SetupHTML as String
Return "<div id=""" + self.ControlID + """>" + html + "</div>"
End Function
Sub Shown() Handles Shown
Init
End Sub
Methods:
Public Sub Init()
Dim par As String
par = ReplaceAll(Firebase_Action, "<<Controle>>", self.ControlID)
par = par + EndOfLine.UNIX + a_Logout
Self.HTML = par
End Sub
Public Sub Logout()
Session.Cookies.Remove("user")
Session.Cookies.Remove("nome")
Self.HTML = "logOut();"
End Sub
Properties:
Public Property HTML as String
Get
Return mHTML
End Get
Set
mHTML = value
If ControlAvailableInBrowser() Then
ExecuteJavaScript(value)
Else
MsgBox("Firebase Widget not available in browser!")
End If
End Set
End Property
Private Property mHTML as String
Shared Methods:
Public Shared Function HTMLHeader(CurrentSession as WebSession) as String
If Not IsLibraryRegistered(CurrentSession, JavascriptNamespace, "lbmdataFireBaseUI") Then
RegisterLibrary(CurrentSession, JavascriptNamespace, "lbmdataFireBaseUI")
Dim sa() As String
sa.Append Firebase_Init
sa.Append "<script>"
sa.Append Firebase_Main
sa.Append a_Logout
sa.Append "</script>"
Return join(sa,EndOfLine.UNIX)
End If
End Function
In my first tests I used some HTML divs in a page, set as a WebPageSource, whose content is below:
<div id="user">UID</div>
<div id="nome">NOME</div>
It worked, but I couldn’t figure how to trigger the Xojo events called by Xojo.triggerServerEvent('<<Controle>>', 'Deslogado', res);
and Xojo.triggerServerEvent('<<Controle>>', 'Logado', res);
So… I embedded the WebControlWrapper (named as FireBase_APL) in a WebContainer along with a WebButton, a WebTimer, a WebTextArea. The button and the textarea area for developing and testing purposes only. The Timer is important for the overall result.
These are the parameters added to the WebContainer:
Event Definitions:
Event Deslogou()
Event Logou(nome As String, uid As String)
Properties:
Private Property logado as Boolean = False
Private Property logadoold as Boolean = True
The code in the Action event of the button is this:
FireBase_APL.Logout
And the code in the Timer.Action event is this:
Dim dd As new Date
Dim j() As String = Array(Session.Cookies.Value("user"), Session.Cookies.Value("nome"))
txt_Feedback.AppendText Join(j) + " - " + dd.ShortTime + EndOfLine
If j(0) = "" Then
logado = False
If Not logado And logadoold Then
RaiseEvent Deslogou
End If
logadoold = False
Else
logado = True
If logado And Not logadoold Then
RaiseEvent Logou(j(0), j(1))
End If
logadoold = True
End If
This is how it works:
The FirebaseUI Widget (not shown here) must have its “signInSuccessUrl” parameter set to your Xojo Web App URL, including the port, if it is a standalone deployment. On CGI deployment (my case), the URL must include the “app.cgi” part.
When the web app receives focus from the browser, the javascript “firebase.auth().onAuthStateChanged” is fired. I have set it to create cookies for the user name and uid (and fire a Xojo triggerevent, that DOES NOT work!).
The timer on the WebContainer checks whether these cookies are set or not and depending on the result, the Events “Logado” (portuguese for logged) and “Deslogado” are raised and treated at the webpage.
I would really appreciate some help in making the Xojo.triggerServerEvents to work. That way I could get rid of the cookies, timer and WebContainer.
For the time being, I consider this to be a working solution!