FastAPI: безопасность с помощью токена firebase

#python #firebase #authentication #fastapi

#python #firebase #аутентификация #fastapi

Вопрос:

Я следую этому руководству, чтобы создать серверную часть api.

Я использую аутентификацию firebase:

  • пользователь вводит адрес электронной почты и пароль во внешнем интерфейсе
    • front отправляет информацию в firebase
    • пользователь аутентификации firebase и токен возврата
    • front хранит токен
  • для любого URL-адреса, требующего авторизации, front отправляет токен в Authorization header ( Bearer xxx )
  • firebase на стороне сервера проверяет токен

В руководстве показано, как это сделать с помощью пароля:

 # creating a dependency
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

async def get_current_user(token: str = Depends(oauth2_scheme)):
    user = fake_decode_token(token)
    return user
  

Но поскольку я использую firebase, нет /token возможности получить токен с паролем.

Я могу проанализировать токен, создав пользовательскую зависимость, например:

 async def parse_token(auth_token:str = Header(...)):
    token = auth_token.split(' ')[1]
    return token

async def get_current_user(token: str = Depends(parse_token)):
    # check the token with firebase auth
    user = auth.verify_id_token(token)
    return user
  

Но теперь я должен все проверять и возвращать исключения вручную.

Есть ли способ FastAPI для этого?

Комментарии:

1. Привет, @junming-wang, я пытаюсь реализовать что-то в этом роде, используя Firebase для аутентификации и используя FastApi для конечных точек, у тебя это работает? Хотелось бы услышать правильный способ, если он будет реализован

2. Мне также любопытно, как вы, наконец, приступили к своей реализации. На самом деле у меня похожий вариант использования, и я немного озадачен тем, как действовать дальше.

Ответ №1:

Просто игнорируйте это.

Конечная /token точка используется для аутентификации и генерации токена (при успешной попытке). Это просто страница / форма входа в систему. Вы просто пропускаете эту часть и используете зависимость, которая будет выполнять проверку.

Конечно, вы должны придерживаться того же имени и расположения OAuth2Password материала.

Помните, что HTTP не имеет состояния, и токены используются для запоминания того, что пользователь уже предоставил идентификацию. Если у вас есть действительный токен, вы также можете поменять его местами на другом компьютере и использовать (если только в файле cookie не хранятся какие-либо файлы cookie безопасности и информация, связанная с компьютером).

Если вы продолжите учебник, на который вы ссылались, вы перейдете к окончательному коду с аутентификацией. Просто укажите токен firebase в "Authorization: Bearer {token}" ваших запросах от внешнего интерфейса к серверной части, и он будет работать.

Ниже ссылка на документацию.

https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/

Ответ №2:

У меня был похожий вариант использования, и при поиске в Google я получил этот вопрос. Но мне это не очень помогло. После дальнейших исследований я наткнулся на этот пост, который очень помог. Просто создайте зависимость следующим образом;

 from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from fastapi import Depends, HTTPException, status, Response
from firebase_admin import auth, credentials
import firebase_admin

cred = credentials.Certificate('./account_key.json')
firebase_admin.initialize_app(cred)

def get_user(res: Response, cred: HTTPAuthorizationCredentials=Depends(HTTPBearer(auto_error=False))):
    if cred is None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Bearer authentication required",
            headers={'WWW-Authenticate': 'Bearer realm="auth_required"'},
        )
    try:
        decoded_token = auth.verify_id_token(cred.credentials)
    except Exception as err:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=f"Invalid authentication credentials. {err}",
            headers={'WWW-Authenticate': 'Bearer error="invalid_token"'},
        )
    res.headers['WWW-Authenticate'] = 'Bearer realm="auth_required"'
    return decoded_token
  

Затем добавьте зависимость от конечных точек, которые вы хотели бы защитить, следующим образом

 async def hello_user(user = Depends(get_user))
  

Это хорошо интегрируется с конечной точкой Swagger, и затем вы можете получать
idToken свои запросы и просто использовать их по своему усмотрению. Большое спасибо постеру