Проверка аутентификации на сервере GraphQL на базе Python с использованием FastAPI

У меня проблемы с реализацией проверки аутентификации на сервере GraphQL, построенном с помощью FastAPI. Раньше мы использовали REST, но теперь мы переходим на GraphQL, и мне интересно, как я могу это реализовать. Раньше у нас были разные маршрутизаторы, и с FastAPI легко проверить аутентификацию на основе маршрутов с использованием зависимостей, как в здесь. Мы отправляем токен в заголовке авторизации, который декодируем в бэкэнде, и получаем обратно user_id, который затем можем использовать в наших различных конечных точках.

Мне интересно, как это может работать с использованием GraphQL здесь. Мы используем Graphene, и я взглянул на Примеры аутентификации Starlettes, а также введение в настройку GraphQl

import binascii
from fastapi import FastAPI
from starlette.authentication import (
    AuthenticationBackend, AuthenticationError, SimpleUser, AuthCredentials
)
from starlette.graphql import GraphQLApp
from starlette.middleware import Middleware
from starlette.middleware.authentication import AuthenticationMiddleware

from schemas.root import my_schema


class BasicAuthBackend(AuthenticationBackend):
    async def authenticate(self, request):
        if "Authorization" not in request.headers:
            raise AuthenticationError('No auth credentials')

        auth = request.headers["Authorization"]
        try:
            id_token = auth.split('Bearer ')[1]
            decoded_token = auth.verify_id_token(id_token)

        except (ValueError, UnicodeDecodeError, binascii.Error) as exc:
            raise AuthenticationError('Invalid basic auth credentials')

        user_id = decoded_token['uid']
        return AuthCredentials(["authenticated"]), user_id


middleware = [
    Middleware(AuthenticationMiddleware, backend=BasicAuthBackend())
]

my_schema = Schema(
    query=RootQuery,
    mutation=RootMutation,
)

api = FastAPI(title=f"MyGraphQLServer", middleware=middleware)
api.add_route("/graphql", GraphQLApp(schema=my_schema))

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


person jmandt    schedule 03.08.2020    source источник


Ответы (1)


В документации FastAPI или документации по старлетке используется add_route, это способ добавления маршрута в Starlette без объявления конкретной операции (как в случае с .get (), .post () и т. Д.). Но у него есть некоторые недостатки, мы не можем добавлять зависимости, как в FastAPI, пример ниже

app.add_route(
"/graphql",
GraphQLApp(schema=graphene.Schema(query=Query), 
executor_class=AsyncioExecutor),
    dependencies=(Depends(SomeAuthorizationStuffHere)),
)

Итак, нам нужно сделать в FastAPI, я создал простое приложение с HTTPBasicAuth, вы можете расширить его с помощью других методов, вам просто нужно включить router(s)

from fastapi import Query, Depends, Request, FastAPI, APIRouter
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import graphene
from graphene import Field, Schema, String, ObjectType
from starlette.graphql import GraphQLApp


router = APIRouter()
app = FastAPI()
security = HTTPBasic()


class Query(ObjectType):
    hello = Field(String, name=String())

    def resolve_hello(root, info, name):
        coverage = info.context["request"].state.some_dep
        return f"Hello {some_dep.some_method(name)}"


graphql_app = GraphQLApp(schema=Schema(query=Query))


@router.api_route("/gql", methods=["GET", "POST"])
async def graphql(request: Request):
    return await graphql_app.handle_graphql(request=request)


app.include_router(router, dependencies=[Depends(security)])
person Yagiz Degirmenci    schedule 05.08.2020
comment
Он не отображает graphiql ide {подробно: метод запрещен} - person Amiya Behera; 06.12.2020
comment
@ app.api_route (/ graphql, methods = [GET, POST]) - person smentek; 15.01.2021