GraphQL Golang Аутентификация с помощью JWT - PullRequest
0 голосов
/ 06 апреля 2020

У меня есть API-интерфейс GraphQL, который я писал в go и задаюсь вопросом, как управлять аутентификацией JWT, когда вы уже используете context для передачи источников данных.

Итак, сокращенная версия Моя main функция:

import (
    "net/http"
    "github.com/graphql-go/graphql"
    gqlhandler "github.com/graphql-go/handler"
)

func queryHandler(ds *sources.DataSources, gql *gqlhandler.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ctx := context.WithValue(context.Background(), sources.CtxSourcesKey, ds)
        gql.ContextHandler(ctx, w, r)
    })
}

func main() {
    apiSchema, _ := schema.CompileSchema(schema.QueryType, schema.MutationType)
    gql := gqlhandler.New(&gqlhandler.Config{
        Schema:     &apiSchema,
        GraphiQL:   !isDeployed,
        Pretty:     false,
        Playground: false,
    })
    http.ListenAndServe(":41000", util.CreateChiRouter(healthCheckHandler(), queryHandler(ctxSources, gql)))
}

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

Каков наилучший способ go об этом, учитывая мою текущую ситуацию? (Объединить JWT с контекстом источников данных? Обрабатывать источники данных по-разному, чтобы освободить context?)

1 Ответ

1 голос
/ 06 апреля 2020

Распространенным способом работы с такими заголовками аутентификации является использование промежуточного программного обеспечения для аутентификации и добавления информации аутентификации в текущий контекст.

В настоящее время вы создаете новый контекст. Я предлагаю использовать существующий HTTP-контекст и добавить к нему, чтобы вы могли связывать вещи:

ctx := context.WithValue(r.Context(), sources.CtxSourcesKey, ds)
newReq:=r.WithContext(ctx)
gql.ContextHandler(ctx, w, newReq)

И вы можете установить промежуточное ПО, которое делает то же самое:

type autoInfoKeyType int

const authInfoKey authInfoKeyType=iota

func GetAuthInfo(ctx context.Context) *AuthInfo {
   if v:=ctx.Value(authInfoKey); v!=nil {
     return v.(*AuthInfo)
   }
   return nil
}

func AuthMiddleware(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    authInfo:=processJWT(...)
    if authInfo!=nil {
       ctx := context.WithValue(r.Context(), authInfoKey, authInfo)
       r=r.WithContext(ctx)
    }
    next.ServeHTTP(w,r)
  }
}

Таким образом, Вы можете проверить, есть ли у контекста информация об аутентификации, и если это так, используйте ее.

if authInfo:=GetAuthInfo(req.Context()); authInfo!=nil {
  ...
}
...