2

I'm working on a mobile site, hosted with Node.js / Express and which is "lightly" secured via Firebase Phone Authentication. When first loaded, the site is basically empty. After initial Firebase Phone authentication, the JWT token is sent to the node server via AJAX call. Server checks token, verifies the user is authorized, then sends back html content for the site.

So far, so good. This is a great way to protect display content on a simple single page web app.

But here is my current dilemma. I now want to submit data from a form on the site. The blank form was created with the first AJAX call.

After form submit, I'd like to resubmit the same JWT token to accompany an additional AJAX request for data submission to the server. It's not clear to me on how to obtain the token. I'm no longer inside the chained promise that got me the token in the first place... (i.e. I don't have access to the User Object anymore.) I can see the token stored in IndexedDB --> FirebaseLocalStorageDB --> FirebaseLocalStorage Object --> Key: Value (fbase_key.value.stsTokenManager.accessToken )

Here's a screen print of my dev tools in Chrome Browser.

Chrome Browser Dev Tools Screen Print

I'm really not sure how to access that token from JavaScript in the browser client. Any ideas on how to get there from here?

Note: All of my initial client script code was contained within

$(document).ready(function () {
...
}

Because of timing and function .on() binding, the subsequent script content for my data form was served after the initial Ajax call post authentication.

Sample code for the initial AJAX submit... Obviously the form data submit to the server will contain a JSON object payload.

    var authUserAjaxRequest = function (jwt) {
        console.log("authUserAjaxRequest started...");
        $.ajax({
            type: "POST", 
            url: '/fb', //the url to call
            data: {
                data: 'testData'
            }, //Data sent to server
            dataType: "json",
            beforeSend: function (xhr) { //Include the bearer token in header
                xhr.setRequestHeader("Authorization", 'Bearer ' + jwt)
            }
        }).then(function (response) {
            $('#admin_note_loc').html(response.admin_note);
            $('#page2_data').html(response.page2_data);
            $('#page3_summary').html(response.page3_summary);
            $('#page4_team').html(response.page4_team);
        }).fail(function (err) {  //Error during request
        console.log("AuthUserReq Error: ", err);
    });

Here's a reference. And another. This reference seems pretty outdated, or I'm just doing it wrong. Specific hints are appreciated.

zipzit
  • 3,778
  • 4
  • 35
  • 63

2 Answers2

1

Here's a solution, but it may not be the best one.

I've got a slight scope issue. For all of my original javascript code I'm using

$(document).ready(function () {
...
}

That code works great, allows me to authenticate, obtain tokens, resubmit, etc.

In there I had some code

var handleSignedInUser = function (user) {
    // do stuff to display / block key elements on the site.

    user.getIdToken().then(function (token) {
        console.log("getIdToken(): ", token);  // <--  I added this line
        authUserAjaxRequest(token);
    })
};

Unfortunately because of the nature of my Ajax additions, I was unable to include their controlling JavaScript within the $(document).ready() wrap. Had some issues binding $().on('click'..) functions to the newly created form elements.

Hmmm. Remember the good 'ol days when we used Microsoft Foundation Classes (MFC) and we added handles to link key features? That gave me an idea.

I added a Global variable, var firebaseGlobalObject = {}; to my original script ahead of $(document).ready(function () {...

And after I initialized my Firebase Authentication tools, I made a copy to the Global variable...

// Initialize Firebase
var config = {
    apiKey: "...",
    authDomain: "....firebaseapp.com",
    databaseURL: "https://....firebaseio.com",
    projectId: "...",
    storageBucket: "...",
    messagingSenderId: "..."
};
firebase.initializeApp(config);
firebaseGlobalObject = firebase;   // <--- total hack

And then it was time to play in the Chrome Dev Tools Console...

I came up with this beauty...

console.log(firebaseGlobalObject.auth().currentUser.qa)

Total hack, but it definitely displays EXACTLY the same token as the getIdToken() (in my initial code) and as displayed at IndexedDB --> FirebaseLocalStorageDB --> FirebaseLocalStorage Object --> Key: Value (fbase_key.value.stsTokenManager.accessToken )

Obviously when I'm using the console, I'm in global context. So I think I can make this work. I will say, I have no clue why someone chose .qa for that index. There is a bunch of descriptive properties visible at firebaseGlobalObject.auth().currentUser; just not that token.

Does anyone have an alternative answer to this dilemma, besides a hack (that will probably fail with the next firebase update X months from now?)

zipzit
  • 3,778
  • 4
  • 35
  • 63
1
firebase.auth().currentUser.getIdToken(true)
.then((tokenId)=>{
//Your code
})

https://firebase.google.com/docs/auth/admin/verify-id-tokens#web