How to solve for authentication error in Python

Question:

I am trying to authenticate the user while running a code in python, but running into an error, "422 Unprocessable Entity". The code is running fine without the authentication, but I am unable to pass request.

from typing import Union
import requests
import uvicorn
from auth import authenticate
from fastapi import FastAPI
import boto3
import json

app = FastAPI()

client = boto3.client('eks')
boto3.set_stream_logger('')


@app.get("/test")
def test(request):
    token = authenticate(request)
    print("test")

if __name__ == "__main__":
    print()
    uvicorn.run(app, host="0.0.0.0", port=8000)

Code for authentication:


import jwt
from general.config import constants
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import APIException
from rest_framework.response import Response
jwtPrivateKey = constants.PRIVATE_KEY


def authenticate(request):
    try:

        auth_header_value = request.META.get("HTTP_AUTHORIZATION", "")
        if auth_header_value:
            if len(auth_header_value.split(" ", 1)) == 2:
                authmeth, auth = request.META["HTTP_AUTHORIZATION"].split(
                    " ", 1)

                if authmeth.lower() != "bearer" and authmeth.lower() != "basic":
                    raise TokenNotBearer()

                token_value = jwt.decode(
                    jwt=auth, key=jwtPrivateKey, algorithms=['HS256', ])
                return token_value

            else:
                raise TokenNotBearer()
        else:
            raise TokenNotProvided()
    except (TokenExpiredOrInvalid, jwt.DecodeError):
        raise TokenExpiredOrInvalid()


# when token is expired or invalid
class TokenExpiredOrInvalid(APIException):
 ...

# when token is not provided
class TokenNotProvided(APIException):
   ...

# when the token is not provided in the bearer
class TokenNotBearer(APIException):
  ...

How can I pass request in the api or how can I work with authentication passing request?

Asked By: Ritika

||

Answers:

You need to mention Request on type annotation explicitly.

UPDATE:
This is not related to type annotation. See another answer.

Try this,

from typing import Union
import requests
import uvicorn
from auth import authenticate
# fix here 
from fastapi import FastAPI, Request
import boto3
import json

app = FastAPI()

client = boto3.client('eks')
boto3.set_stream_logger('')

# fix here
@app.get("/test")
def test(request: Request):
    token = authenticate(request)
    print("test")

if __name__ == "__main__":
    print()
    uvicorn.run(app, host="0.0.0.0", port=8000)
Answered By: rumbarum

@Ritika You are authenticating FastApi with django-restframework. reqeuste are not same on both app.
Django get header from request instance, but Fastapi get header directly.

** Notice:
function param authorization should match your header name!
if your header Name is not Authorization, then fix it.

This may works,

# main.py 

from typing import Union
import requests
import uvicorn
from auth import authenticate
# fix here
from fastapi import FastAPI, Header
import boto3
import json

app = FastAPI()

client = boto3.client('eks')
boto3.set_stream_logger('')

# fix here
@app.get("/test")
def test(authorization:str = Header(default=None)):
    token = authenticate(authorization)
    print("test")

if __name__ == "__main__":
    print()
    uvicorn.run(app, host="0.0.0.0", port=8000)

# auth.py

import jwt
from general.config import constants
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import APIException
from rest_framework.response import Response
jwtPrivateKey = constants.PRIVATE_KEY


def authenticate(auth_header_value):
    try:
        if auth_header_value is not None:
            if len(auth_header_value.split(" ", 1)) == 2:
                authmeth, auth = auth_header_value.split(
                    " ", 1)

                if authmeth.lower() != "bearer" and authmeth.lower() != "basic":
                    raise TokenNotBearer()

                token_value = jwt.decode(
                    jwt=auth, key=jwtPrivateKey, algorithms=['HS256', ])
                return token_value

            else:
                raise TokenNotBearer()
        else:
            raise TokenNotProvided()
    except (TokenExpiredOrInvalid, jwt.DecodeError):
        raise TokenExpiredOrInvalid()


# when token is expired or invalid
class TokenExpiredOrInvalid(APIException):
 ...

# when token is not provided
class TokenNotProvided(APIException):
   ...

# when the token is not provided in the bearer
class TokenNotBearer(APIException):
  ...
Answered By: rumbarum