0

I am trying to deploy a site to firebase, with dynamic content being served by Cloud Run via Flask. I am using the flask-login package, and this is working fine locally, when using firebase serve, and it also works perfectly when visitng the Cloud Run app (the stylesheet and other static content are obviously missing).

However, when visiting the firebase site the static content is served, although the login page returns a 401 unauthorized error when logging in.

login.html:

<div class="box">
    <h1>Login</h1>
    <form method="post">
        <input type="text" name="email" placeholder="Email" required="required"/>
        <input type="password" name="password" placeholder="Password" required="required"/>
        <button type="submit" class="btn btn-primary btn-block btn-large">Login</button>
    </form>
</div>

app.py:

@app.route('/login', methods=["GET", "POST"])
def login():
    if request.method == "POST":
        email = request.form.get('email')
        password = request.form.get('password')

        # Email doesn't exist or password incorrect.
        if user.get_id() == email:
            flash("That email does not exist, please try again.")
            return redirect(url_for('login'))
        elif not password == 'xxx':
            flash('Password incorrect, please try again.')
            return redirect(url_for('login'))
        else:
            login_user(user)
            return redirect(url_for('secrets'))

    return render_template("login.html", logged_in=user.is_authenticated)

@app.route('/secrets')
@login_required
def secrets():
    print(user.name)
    return render_template("secrets.html",
                           name=user.name,
                           logged_in=user.is_authenticated,
                           latest_weight=latest_weight(),
                           )

I am not sure if code will help in this case, I think I must have misunderstood something about the session information is being handled by flask-login. I can't recreate the error outside of the firebase/cloud run environment, so it's quite hard to troubleshoot.

Cloud run logs don't provide any useful information other than a GET request returned a 401.

1 Answers1

2

Well there is a lot to this story, but essentially two things are missing:

  1. Firebase strips cookies. The only cookie that you can use is __session. See this thread and discussions.
    So what you need to do is make sure that for keeping logins between requests you store the cookie as __session.

  2. As each request is routed to a different Cloud Run instance, you need to persist the server-side login information. If you don't have any relational database, the recommendation is using Firestore. There is a guide for flask-login with Firestore that you can follow.

Pentium10
  • 204,586
  • 122
  • 423
  • 502
  • Thanks for that. I figured something was happening with firebase and cookies. You say that each instance is routed to a different Cloud Run instance, but there is no problem with staying logged in on the Cloud Run URL (*.run.app), only on the firestore hosting linke (*.web.app). For the time being I have included the static files within the Cloud Run instance. I am already using firestore for another part of the project, so will look at implementing that--thanks for the link. Not sure why I didn't find that before. – anothersimonharris May 24 '22 at 09:40
  • If works now on Cloud Run, that's probably based on some testing context, but it will be routed to different instance, and if you persist something server side than you need to handle outside of the "vanishing" cloud run instance like firestore. – Pentium10 May 24 '22 at 13:08
  • Ah sorry I misunderstood what you were saying. User data is already stored in firebase, I thought you were saying it would log users out when a new instance was activated, but this isn't the case. – anothersimonharris May 25 '22 at 07:53