0

Right now I'm trying to understand how Firebase authentication works on the backend. It seems like the main method is for the web client to get an id token, and then for every REST request, inject that token into the Authorization http header before sending the request to the backend (official docs, official docs 2, SO answer). Just as a starting point, I cloned a super basic Github project (teroyks - firebase-auth-api) that uses this method, and you can see how the id token injection works on the frontend:

// fetch timestamp from API
// authenticate API request with JWT auth token
const fetchFromApi = userIdToken => {
  return fetch('/api', {
    headers: {
      Authorization: `Bearer ${userIdToken}`,
    },
  })
    .then(response => {
      ...

You can find the full code in the github: frontend backend

However, I'd like to be able to create pages on my website that are only accessible by signed-in users. For example, the path https://www.mywebsite.com/profile should display the current user's profile, and if they aren't authenticated, redirect them to login. But I haven't seen any firebase examples that do this. If the user clicks on a link that goes to https://www.mywebsite.com/profile (maybe it's in their bookmarks or something), the browser makes the GET request and not me, so I have no way of injecting the id token to the request. One workaround I've thought of is to just load a blank page on the initial request, and then the blank page runs the client side code needed to get the id token and retrieve the actual page content from the backend, but this feels very hacky and would prevent server-side rendering. What's the standard way of solving this issue?

woojoo666
  • 7,801
  • 7
  • 45
  • 57

1 Answers1

0

It totally depends whether you are doing a client side rendering or a server side rendering, for example

if you are doing a server side rendering to your html files, you can make a middleware that redirects to /login if there is no accessToken provided in the header check

Node Express - redirect to login view

and if you are doing a client side rendering

 firebase.auth().onAuthStateChanged(user => {
        if (user) {
          content.innerHTML = `<p>Logged in as ${user.displayName}</p>
          <p><button onClick="firebase.auth().signOut();">Logout</button></p>`
          user
            .getIdToken() // this is where firebase gets the token for you 
            .then(token => {
              console.log(`uid token: ${token}`)
              return fetchFromApi(token)
            })
            .then(content => {
              apiContent.innerHTML = content
            })
        } else {
         //redirect to login
          window.location.replace("/login")
        }
      })
scr2em
  • 974
  • 8
  • 17
  • I would like to do server-side rendering. But when you say "make a middleware that redirects to /login if there is no accessToken provided in the header check", how would the accessToken be there if the user is just clicking a link? I have no way of injecting the accessToken to the request – woojoo666 Oct 15 '21 at 18:27
  • when the user login with firebase `loginWithEmailAndPassword` firebase itself creates cookies for you under the hood (with expiration time of 1 hour) that has the accessToken, check their client SDK https://firebase.google.com/docs/auth/web/password-auth – scr2em Oct 15 '21 at 18:36