Search code examples
authenticationflaskflask-login

How do you use a license key/server to authenticate a Flask app?


I have a service that generates a license key, and that provides an API to verify the key is valid, e.g. curl api-url -d "license_key=xxxx" -X post returns json that says if the key is valid or not.

I want to use this for authentication in a flask app, where the user enters their key to login, and the app does the check above to authenticate if they have access. The users don't need a username, the license key is unique to them, and should be all that is needed.

I have not found anything that (at least to my understanding) suggests how to go about this in either https://flask-security-too.readthedocs.io/en/stable/ or https://flask-login.readthedocs.io/en/latest/.

I guess it isn't crucial it is done in Flask, if there is another way to do this with a regular web server.

Does this kind of authentication have a name? I feel like I am not looking for the right information so far.


Solution

  • This can be done using sessions in Flask. You can make the POST request with the requests module.

    from flask import Flask, redirect, url_for, render_template, flash, session
    from flask_wtf import FlaskForm
    from wtforms import StringField, SubmitField
    from wtforms.validators import DataRequired
    import requests
    
    app = Flask(__name__)
    app.config["SECRET_KEY"] = "secret-key-goes-here"  
    
    class LoginForm(FlaskForm):
        license_key = StringField("License key", validators = [DataRequired()])
        submit = SubmitField("Submit")
    
    @app.route("/login", methods=["GET", "POST"])
    def login():
        if session.get("authenticated"):
            return redirect(url_for("index"))
        form = LoginForm()
        if form.validate_on_submit():
            req = requests.post("api-url", {"license_key": form.license_key.data})
            if not req.json()["valid"]:
                flash("Invalid username or password")
                return redirect(url_for("login"))
            session["authenticated"] = True
            return redirect(url_for("index"))
        return render_template("login.html", title="Sign In", form=form)
    

    This assumes the JSON response is of the form {"valid": true/false}.