How to send a password to a Flask app when using Docker/Kubernetes?

9/11/2021

Background:
I know this is a very basic question, but I don't have experience in Frontend apps. I recently tried sending a GET request from a static HTML page to an app running in Docker on a cloud server, and it didn't work. So now instead of an HTML page, I'm trying a Flask app that does authentication.

What I want to do:
Create an index page, where if the user is logged in, they are shown some products. If the user is not logged in, they are shown a login form to type their email id and password.
The Flask app will be deployed in Docker and be available via Kubernetes Ingress, on a Kubernetes cloud cluster. My main worry is about how the username and password will find its way from the client-side browser to the correct service. Is it done via a POST generated at the HTML page itself? Won't the POST request have to point to some specific URL? Should hashing the password be done by some JQuery script when the Login button is clicked?

What I'm unable to figure out:
Even after seeing a lot of examples, I'm unable to figure out the right way to hash and send a password to the Flash app, when the user types their email and password and clicks the "Login" button. Then if the user is logged in, it has to render an HTML page with the products shown.

If there's a simple way to do it without flask-httpauth (install with pip install flask-httpauth) or if there's a library that has cleaner syntax, that technique is also welcome.

Flask Code:

#!flask/bin/python
from flask import Flask, jsonify, abort, request, make_response, url_for
from flask_httpauth import HTTPBasicAuth

app = Flask(__name__, static_url_path = "")
auth = HTTPBasicAuth()

@app.route('/')
@auth.login_required
def welcome():
    return render_template('index.html')

@app.route('/logout')
def welcome():
    return render_template('logout.html')

@auth.error_handler
def unauthorized():
    return '<!DOCTYPE html><html><body><div style="text-align: center;">Unauthorized access</div></body></html>'
    
@app.errorhandler(400)
def not_found(error):
    return '<!DOCTYPE html><html><body><div style="text-align: center;">Bad request</div></body></html>'

@app.errorhandler(404)
def not_found(error):
    return '<!DOCTYPE html><html><body><div style="text-align: center;">Page not found</div></body></html>'

if __name__ == '__main__':
	app.run(debug=True, host="0.0.0.0")

Login page: index.html

   <!DOCTYPE html>
  <html>
    <head>
      <meta charset="UTF-8" />
      <title>Vacation Finder</title>
      <!--Import materialize.css-->
      <link type="text/css" rel="stylesheet" href="materialize.min.css"/>
      <!--Let browser know website is optimized for mobile-->
      <meta name="viewport" content="width=device-width, initial-scale=1.0"/>          
    </head>

    <body>
        <div>
          <nav>
            <div class="nav-wrapper grey darken-4">
              <div style="text-align: center; font-size: 30px; font-weight: bold;">Some page</div>
                <div class="row">
	                <div class="col s12 m8 l4 offset-m2 offset-l4">
                        <br>
                        <br>
		                <div class="card">
			                
			                <div class="card-content">
			                
                                  <div class="row">
                                    <div class="input-field col s12">
                                      <input id="email" type="email" class="validate">
                                      <label for="email">Email</label>
                                    </div>
                                  </div>

                                  <div class="row">
                                    <div class="input-field col s12">
                                      <input id="password" type="password" class="validate">
                                      <label for="password">Password</label>
                                    </div>
                                  </div>

					              <button id="login" class="waves-effect waves-light btn blue darken-1" style="width:100%;">Login</button>
				                <br>
			                </div>

		                </div>
	                </div>
                </div>
            </div>
          </nav>
        </div>
  
    </body>
  </html> 
-- Nav
docker
flask
kubernetes
python

1 Answer

9/11/2021

You can use the JWT token if you want

https://geekflare.com/securing-flask-api-with-jwt/

@app.route('/login', methods=['GET', 'POST'])  
def login_user(): 
 
  auth = request.authorization   

  if not auth or not auth.username or not auth.password:  
     return make_response('could not verify', 401, {'WWW.Authentication': 'Basic realm: "login required"'})    

  user = Users.query.filter_by(name=auth.username).first()   
     
  if check_password_hash(user.password, auth.password):  
     token = jwt.encode({'public_id': user.public_id, 'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=30)}, app.config['SECRET_KEY'])  
     return jsonify({'token' : token.decode('UTF-8')}) 

  return make_response('could not verify',  401, {'WWW.Authentication': 'Basic realm: "login required"'})

apart of this you can also check official bookinfo app istio example : You can also check this example : https://github.com/istio/istio/tree/master/samples/bookinfo/src/productpage

JWT : https://medium.com/@apcelent/json-web-token-tutorial-with-example-in-python-df7dda73b579

https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/

https://realpython.com/token-based-authentication-with-flask/

-- Harsh Manvar
Source: StackOverflow