[Python] Use Basic/Digest authentication with Flask

Introduction

The other day, my uncle implemented the REST API in Flask only. With the momentum, I decided to add an authentication function because it was a big deal. I'm an amateur, but when I was researching, I came across basic authentication and Digest authentication. Aside from how it works, I've been able to move the code, so make a note of it.

I referred to the following. (Rather, it's almost the same.)

Also, I think it's best to read the tutorials on the following sites.

-flask_httpauth tutorial:
https://flask-httpauth.readthedocs.io/en/latest/ -requests page:
https://requests-docs-ja.readthedocs.io/en/latest/user/authentication/

Basic authentication

It seems to be a method of writing the user name and password as they are in the HTTP request and sending it. On the receiving server side, I used a module called flask_httpauth.

python -m pip install --upgrade pip
python -m pip install flask
python -m pip install flask_httpauth 

Preparing the server

This is the server-side code used to check the operation. I wonder if there is a more convenient implementation method such as password confirmation, but it worked for the time being, so I will write it down.

server_basicauth.py


from flask import Flask
from flask_httpauth import HTTPBasicAuth

app = Flask(__name__)
auth = HTTPBasicAuth()
id_list = {
    "user001": "password1111",
    "user002": "password1234"
}

@auth.get_password
def get_pw(id):
    id_list.get(id)

@app.route('/')
@auth.login_required
def index(): 
    return "Hello, %s!" % auth.username()

if __name__ == '__main__':
    app.run()

Let's start it for the time being.

$ python server_basicauth.py
 * Serving Flask app "server_basicauth" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off

Send an HTTP request

You can also implement in python where to send an HTTP request to this server. It seems that there are various modules that can be used, but here we will use requests.

request_basicauth.py


import requests
for pswd in ["password1111", "password2222"]:
    usr = "user001"
    print("authtication test: user={}, password={}".format(usr, pswd))
    r = requests.get('http://localhost:5000/', auth=(usr, pswd))
    print("response:", r.status_code)
    print(r.content)
    print(r.headers)
    print("------------------------------------------------------")

If you run it with python request_basicauth.py in another terminal with the server started, you will get the following result.

authtication test: user=user001, password=password1111
response: 200
b'Hello, user001!'
{'Content-Type': 'text/html; charset=utf-8', 'Content-Length': '15', 'Server': 'Werkzeug/1.0.1 Python/2.7.17', 'Date': 'Sat, 02 Jan 2021 13:06:21 GMT'}
------------------------------------------------------
authtication test: user=user001, password=password2222
response: 401
b'Unauthorized Access'
{'Content-Type': 'text/html; charset=utf-8', 'Content-Length': '19', 'WWW-Authenticate': 'Basic realm="Authentication Required"', 'Server': 'Werkzeug/1.0.1 Python/2.7.17', 'Date': 'Sat, 02 Jan 2021 13:06:22 GMT'}
------------------------------------------------------

As expected, the first password will authenticate and return 200, but the next will return 401.

Also, if you enter https: // localhost: 5000 in a browser such as Chrome, you will be asked for the password. When I typed it, Hello user001 was output.

Digest authentication

This also worked in the same way. The only difference from Basic authentication is that flask_httpauth uses HTTPDigestAuth.

First, the server side. You will need the private key when you start the server side. Here, it is embedded in the code as it is.

server_httpauth.py


from flask import Flask
from flask_httpauth import HTTPDigestAuth

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret key here'
auth = HTTPDigestAuth()

id_list = {
    "user001": "password1111",
    "user002": "password2222"
}

@auth.get_password
def get_pw(id):
    return id_list.get(id)

@app.route('/')
@auth.login_required
def index(): 
    return "Hello, %s!" % auth.username()

if __name__ == '__main__':
    app.run()

Similarly, the client side can be implemented with just requests.

request_digestauth.py


import requests
from requests.auth import HTTPDigestAuth

for passwd in ["password1111", "password2222"]:
    r = requests.get('http://localhost:5000/', auth=HTTPDigestAuth('user001', passwd))
    print(r.status_code)
    print(r.headers)
    print(r.content)

If you start the server and move the request side in another terminal, it will be as follows.

200
{'Date': 'Sat, 02 Jan 2021 13:22:43 GMT', 'Vary': 'Cookie', 'Content-Length': '15', 'Content-Type': 'text/html; charset=utf-8', 'Server': 'Werkzeug/1.0.1 Python/2.7.17'}
Hello, user001!
401
{'Content-Length': '19', 'Set-Cookie': 'session=.eJyrVkosLcmIz8vPS05VsqpWUkhSslLyC4nK9HWJyvI18qzyzfXLjAxJLo_K9TWNzIrKjgoJy_WtijTyd3c19A93tVWq1YEYkV-QWFiKMCPK3bcqKjwo1x9ojp-Ra3lUVmRVlItTdpRLpIG_S0pGlLtfDsTsdKAZtQAJAC0F.X_Bzow.s0xYY1rqLai75_11dFa7PMOkhck; HttpOnly; Path=/', 'Vary': 'Cookie', 'Server': 'Werkzeug/1.0.1 Python/2.7.17', 'Date': 'Sat, 02 Jan 2021 13:22:43 GMT', 'Content-Type': 'text/html; charset=utf-8', 'WWW-Authenticate': 'Digest realm="Authentication Required",nonce="56b06c3b32cba70fc9b6de5f3668a59a",opaque="dc3edf86c7a0f63d0dd6487adce2cba8"'}
Unauthorized Access

I was able to confirm that if the user name and password are correct, it will be OK, otherwise 401 Unauthorized Access will be returned.

Summary

For the time being, I was able to run Basic authentication and Digest authentication.

--There is a lot of information when you read the flask_httpauth page! Various things such as token authentication, role setting, session, server authentication, etc. were written. Can it be used? .. .. --It may be necessary to prepare for CI/CD without raising the private key to github etc. --The user name and password are embedded in the code this time, but when increasing the number of users one by one. .. .. I want to know the general method. ――As for flask in general, what should I do when organizing the code?

There are some things that seem absurd, but today (the second day of the new year) I will leave it around here.

Recommended Posts

[Python] Use Basic/Digest authentication with Flask
Use mecab with Python3
Use DynamoDB with Python
Use Python 3.8 with Anaconda
Use python with docker
Programming with Python Flask
Flow to complete Slack authentication with Flask (Python)
Use Trello API with python
BASIC authentication with Python bottle
Use Twitter API with Python
Use TUN / TAP with Python
Web application with Python + Flask ② ③
Use subsonic API with python3
Web application with Python + Flask ④
Python: How to use async with
Use PointGrey camera with Python (PyCapture2)
Use vl53l0x with Raspberry Pi (python)
SNS Python basics made with Flask
Use NAIF SPICE TOOLKIT with Python
Next, use Python (Flask) for Heroku!
Use rospy with virtualenv in Python3
Basic authentication and Digest authentication with Flask
Use Python in pyenv with NeoVim
How to use FTP with Python
Use Windows 10 speech synthesis with Python
Use OpenCV with Python 3 in Window
Use PostgreSQL with Lambda (Python + psycopg2)
Application development with Docker + Python + Flask
Sample to use after OAuth authentication of BOX API with Python
Use boto3 with temporary credentials with SAML authentication
Use smbus with python3 under pyenv environment
Passwordless authentication with RDS and IAM (Python)
Use Amazon Simple Notification Service with Python
POST variously with Python and receive with Flask
Page cache in Python + Flask with Flask-Caching
[Python] Use string data with scikit-learn SVM
[Introduction to Python] Let's use foreach with Python
Use PIL and Pillow with Cygwin Python
Use cryptography library cryptography with Docker Python image
Easy web app with Python + Flask + Heroku
Use Application Insights with Python 3 (including bottles)
[Python] Quickly create an API with Flask
Use C ++ functions from python with pybind11
Use selenium phantomjs webdriver with python unittest
Until you can use opencv with python
Use Python and MeCab with Azure Functions
Statistics with python
Python with Go
Twilio with Python
Integrate with Python
Play with 2016-Python
AES256 with python
Tested with Python
python starts with ()
with syntax (Python)
Bingo with python
Zundokokiyoshi with python
Python Https Authentication
Excel with Python
Flask Basic authentication
Microcomputer with Python