1

i am new in this part of programming and i have few questions. First of all my project. At one side i have a Flutter App and at the other side a MS SQL Server with data. This data i need on my device logically. I read the best way is to use FastAPI, its easy and has a good performance but i am not sure about security. I read something about OAuth2 but it looks to much because just one user will have permission to use the data (the server owner). Is it possible just to use a simple api key as a parameter? Something like this...

from fastapi import FastAPI
from SqlServerRequest import SqlServerRequest

app = FastAPI()


@app.get("/openOrders/{key}")
async def openOrders(key):
    if key == "myverysecurekey":
         return "SQLDATA"
    else
         return "Wrong key"

That way works but i am not sure about the security What would you say?

Shajko
  • 107
  • 2
  • 8

2 Answers2

4

I have been dealing with the same issue for a while. Instead of using a oauth I needed a simple X-API-Key in the header.

You can do that with the following code

from fastapi import FastAPI, Depends
from fastapi.security import APIKeyHeader
import os

os.environ['API-KEY'] = '1234'. 
# You would use as an environment var in real life

X_API_KEY = APIKeyHeader(name='X-API-Key')


def api_key_auth(x_api_key: str = Depends(X_API_KEY)):
    """ takes the X-API-Key header and validate it with the X-API-Key in the database/environment"""
    if x_api_key != os.environ['API-KEY']:
        raise HTTPException(
            status_code=401,
            detail="Invalid API Key. Check that you are passing a 'X-API-Key' on your header."
        )


app = FastAPI()


@app.get("/do_something", dependencies=[Depends(api_key_auth)])
async def do_something():
    return "API is working OK."
1

If your use case is just to serve a single user, and is not mission-critical, this might be a good way to start.

main.py

import os

import uvicorn
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from starlette import status

# Use token based authentication
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")


# Ensure the request is authenticated
def auth_request(token: str = Depends(oauth2_scheme)) -> bool:
    authenticated = token == os.getenv("API_KEY", "DUMMY-API-KEY")
    return authenticated


app = FastAPI()


@app.get("/openOrders")
async def open_orders(authenticated: bool = Depends(auth_request)):
    # Check for authentication like so
    if not authenticated:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Not authenticated")

    # Business logic here
    return {"message": "Authentication Successful"}


if __name__ == '__main__':
    uvicorn.run("main:app", host="127.0.0.1", port=8080)

You can run this using python main.py

The client can then make requests like so:

import requests

url = "http://127.0.0.1:8080/openOrders"
payload={}
# The client would pass the API-KEY in the headers
headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer DUMMY-API-KEY'
}
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)

Client code in Dart

final response = await http.get(
  Uri.parse('http://127.0.0.1:8080/openOrders'),
  // Send authorization headers to the backend.
  headers: {
    HttpHeaders.authorizationHeader: 'Bearer DUMMY-API-KEY',
  },
);
Shajko
  • 107
  • 2
  • 8
Raqib
  • 1,367
  • 11
  • 24
  • Thx, for quick answer, but a few things i dont get. This line: authenticated = token == os.getenv("API_KEY", "DUMMY-API-KEY") - Where i get this api keys? Is this generating by fastapi? And the code for client is for what? i have to connect with my flutter mobile app with an url?! to get the response in json and sorry when i don't get something obvious like i said i am new at this things – Shajko Jun 11 '21 at 22:26
  • When the client (you flutter app) makes a request, it needs to add ` 'Authorization': `Bearer DUMMY-API-KEY'` to the request header. When the FastAPI application receives this request, the request will have have to be authenticated. How? `authenticated: bool = Depends(auth_request)` takes care of that. – Raqib Jun 11 '21 at 22:29
  • I have added an edit with Dart code that you can use in your flutter app to call the FastAPI app. I do not know any Dart or Flutter – Raqib Jun 11 '21 at 22:33
  • ok thx, one more think, how it looks like if i just want to open it in chrome, how would look the url? – Shajko Jun 11 '21 at 22:39
  • I would use something like Postman or Insomnia for API development. It is much easier in my opinion than to use a browser for API development. The URL will look like `http://127.0.0.1:8080/openOrders` but as you are using browser, I am not sure how you would send headers in a browser. – Raqib Jun 11 '21 at 22:41
  • I wanted somethink like that: https://api.bittrex.com/api/v1.1/account/getbalances?apikey=API_KEY for example and use a fix apikey and that was is – Shajko Jun 11 '21 at 22:47
  • That in my opinion is very bad practice. What you are trying to do is a query parameter, you can find information about it [here](https://fastapi.tiangolo.com/tutorial/query-params/). Highly not recommended – Raqib Jun 11 '21 at 22:50
  • Why? Its not enough secure? Thx for the link but i tried already and it works. See my first post – Shajko Jun 11 '21 at 23:03
  • From my knowledge, I do not think it is. See https://stackoverflow.com/questions/187655/are-https-headers-encrypted – Raqib Jun 11 '21 at 23:20
  • @Rapib Do you maybe know how to rum the server in background, I mean without console? – Shajko Jun 15 '21 at 23:47