-1

Is it possible to use a secret key to secure just an API without a website or webpage?

I made an app that uses flask and when I test it from the client app, it works. However I want to secure the get request from the client to the server by using a secret key or token if possible.

The problem is that most examples I have seen assumed you are using this for a website with login credentials. I don't have any webpages or any routes in my flask app.

Here is the server side:

from flask import Flask, stream_with_context, request, Response
from flask_restful import Api, Resource
from flask_socketio import SocketIO
import intermedia_choose_action_flask 
import subprocess
from io import StringIO 
import sys
import sqlite_companysearch
import time

app = Flask(__name__)
api = Api(app)
SECRET_KEY = "a long set of strings I got from running a command in linux terminal"

app.secret_key = SECRET_KEY

class addspamblacklistspecific(Resource):
    def get(self, emailordomain):
        count = 0
        sqlite_companysearch.comp_searchall_intermedia()
        selection_cid = sqlite_companysearch.comp_searchall_intermedia.cid_selection_results            
        for cid in selection_cid:
            
            subprocess.Popen(["python3", "/home/tech/scripts/Intermedia_automate/intermedia_choose_action.py", "--addblockspecific", "--cp", cid, "--ed", emailordomain], bufsize=10, errors='replace')
            count = count + 1 
            if count == 3:
                time.sleep(60)
                count = 0

        return "command completed succesfully"

        

api.add_resource(addspamblacklistspecific, "/addspamblacklistspecific/<string:emailordomain>")
if __name__ == "__main__":
    app.run(debug=True)

Here is the client side:

from flask import json
import requests

#where do I put in a secret key?

def email_or_domain_selection():
    email_or_domain_selection.email_select = input("""Enter an email or domain.
(NOTE: domains must have a "*" symbol infront of the name. For example *company.com)

Enter Email or Domain :""")
    eselect = email_or_domain_selection.email_select
    return email_or_domain_selection.email_select
email_or_domain_selection()

BASE = "http://127.0.0.1:5000/"

response = requests.get(BASE + "addspamblacklistspecific/"+email_or_domain_selection.email_select)
print(response.text)

I figure I should learn this before learning how to put my app in the cloud.

Thank you for your time,

Edit - I was told to read this: demystify Flask app.secret_key which I already did. That is for if you have webpages. I don't have any webpages and am just trying to secure an API only. It doesn't explain how or if I should be using session information for just calling an api from a client side. It doesn't explain how to use a secret key on the client side.

  • I suggest you review this article https://stackoverflow.com/questions/22463939/demystify-flask-app-secret-key – Mert Bilgiç May 30 '21 at 09:03
  • I already read that. Google bring you to that link. - That doesn't explain how to use a secret key specifically for ONLY APIs. That is talking about if you have webpages for authetnication as well. Then yes, you need session information. I don't have any webpages, so I don't understand how to use session information here or a secret key. –  May 30 '21 at 09:08

1 Answers1

0

You could look into flask-httpauth. I used this a while back on one of my projects to add a layer of security to some API's running on flask. Keep in mind that this is only a basic authentication (base-64 encoded strings).

from flask import Flask, jsonify, request
from flask_restful import Resource, Api
from flask_httpauth import HTTPBasicAuth


# import credentials from env (suggested)
API_UNAME = "username"
API_PASS = "password"

USER_DATA = {API_UNAME: API_PASS}


# initialize flask/flask-restful instance
app = Flask(__name__)
api = Api(app)
auth = HTTPBasicAuth()


class API_Class(Resource):
    @auth.login_required
    def post(self):
        # do api stuff
        return jsonify("result")


# verify API authentication
@auth.verify_password
def verify(username, password):
    if not (username and password):
        return False
    return USER_DATA.get(username) == password


api.add_resource(API_Class, "/post")

You might want to look into other methods like OAuth for extra security.

Harsh
  • 26
  • 2
  • This looks like the client needs a username and password for this type of authentication, just like with a json web token. Is there any form of authentication that doesn't require a username a password? –  May 30 '21 at 15:24
  • The client does not require a username and password. You need a base64-encoded string "username:password" . So it would look something like this : `Authorization: Basic ZGVtbzpwQDU1dzByZA==` – Harsh May 30 '21 at 17:20