In flask-restplus, I want to render API authentication view for my minimal flask API, where whenever when I make a request to the server, the first API should pop up a protective view for asking the user to provide customized token value before using API call. I came up my solution to make API authentication pop view before using api function, but couldn't get that correctly. Can anyone help me out how to make my code work smooth? Any idea?
My current attempt with full implementation:
Here is the partial code of my implementation to do this task.
from functools import wraps
import requests, json, psycopg2, datetime
from time import time
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
from flask_restplus import Resource, Api, abort, fields, inputs, reqparse
from itsdangerous import SignatureExpired, JSONWebSignatureSerializer, BadSignature
class AuthenticationToken:
def __init__(self, secret_key, expires_in):
self.secret_key = secret_key
self.expires_in = expires_in
self.serializer = JSONWebSignatureSerializer(secret_key)
def generate_token(self, username):
info = {
'username': username,
'creation_time': time()
}
token = self.serializer.dumps(info)
return token.decode()
def validate_token(self, token):
info = self.serializer.loads(token.encode())
if time() - info['creation_time'] > self.expires_in:
raise SignatureExpired("The Token has been expired; get a new token")
return info['username']
SECRET_KEY = "f4b58245-6fd4-4bce-a8a4-27ca37370a3c"
expires_in = 600
auth = AuthenticationToken(SECRET_KEY, expires_in)
db = SQLAlchemy(app)
I pretty much coded up all for API authentication but couldn't get the authentication pop view that I expected in my desired output.
Update: output at server endpoint:
When I tried http://127.0.0.1:5000/token at server endpoint, I got Not Found error. How can I get my desired output? any idea?
I am wondering how can I get api protection view that requires a token to access API. currently, I have an error, couldn't get my desired output, so I am hopeful SO community helps me through with this.
desired output:
I want to render a protective view for test API before using API call on the server endpoint. Here is a mockup API authorization view that I want to get:
how can I make this happen using python flask, flask restful? any thought? thanks
If I understand you correctly, you want to implement a token based implementation similar to JWT authorization.
What JWT is all about is nicely summarized at docs.nginx.com > JWT authorization which says
JWT is data format for user information in the OpenID Connect standard, which is the standard identity layer on top of the OAuth 2.0 protocol. Deployers of APIs and microservices are also turning to the JWT standard for its simplicity and flexibility. With JWT authentication, a client provides a JSON Web Token, and the token will be validated against a local key file or a remote service.
You do not necessarily have to do the JWT on webserver level, but I usually prefer to do authentication on web server level in order to nicely split data (aka endpoints) and security.
Let us now focus on JWT with flask. The blog.teclacode.com nicely summarizes the work flow [comments by me]:
- User provides their username and password [to an extraordinary endpoint]
[The next 3 steps happen within that extraordinary endpoint].
- We verify they are correct inside our Flask app
- We generate a JWT which contains the user's ID.
- We send that to the user.
- Whenever the user makes a request to our application, they must send us the JWT we generated earlier.
I guess your challenge spans steps 1 through 4. Step 5 you seem to have implemented already: It is the un-secured endpoint(s) plus an additional, mandatory POST-parameter token. Those endpoints will give back data to the client once a valid token is provided. In other words: Each ordinary endpoint calls a function which validates a given token. Is this understanding correct? Is step 5 already working for you?
I never implemented JWT with python, but a quick search for packages with JWT in their names give me the impressions that there are many ready-to-use token generators out there you "just" have to configure.
A couple of questions about your code:
We can make that file beautiful and searchable if some errors are corrected.
user_db defined? You mentioned that in a comment, but I cannot find that elsewhere. It would be helpful to have a paragraph on this in your question.http://127.0.0.1:5000/token is an endpoint which provides the token, but I do not fully understand from the question in its current form where the endpoint /token is implemented.As the comments suggest, there's no simple snippet of code anyone can share to answer this question. You're basically asking for a five-part blog on how to attach a database to a Flask app in order to authenticate API credentials. I know it doesn't seem this way, but your questions really cascade from one topic Yinto the next. I think your best bet is to look at the Flask Mega Tutorial Part IV Databases and Part V User Logins. These tutorials cover the foundational concepts your code seems to be missing, as follows:
For what it's worth, I really think The Flask Mega-Tutorial would be helpful.
UPDATE: Here is a minimal example using a dictionary as a toy database. A few things about this example ...
If you run main.py and go to http://127.0.0.1:5000/token?username=admin&password=somepassword you will see the working get example
If you go to http://127.0.0.1:5000, click on "hello_world", click "post", and then click "try it out," you can enter a username and a password, and those will be added to the mock database.
After adding a username and password, you can go to http://127.0.0.1:5000/token?username=[]&password=[] except replace brackets with that new username and password. If you shutdown the server, the usernames and passwords won't be saved since it's just updating a dictionary.
Hopefully, all this helps ... once you've edited the app like this, it should be easier to debug issues that aren't related to username and password authentication.