gqlgen
gqlgen copied to clipboard
How do i create `skipAuth` directives.
What happened?
I am working on adding a skipAuth directives to queries that will render certain queries accessible to the public, provided the skipAuth directive is specified.
What did you expect?
Referring to this document (https://gqlgen.com/reference/directives/), the directive operates subsequent to the authorization middleware. My goal is to find a strategy that facilitates the execution of the directive or checks if skipAuth
is specified within the auth middleware before moving forward.
Minimal graphql.schema and models to reproduce
type Query {
gates: Gate! @skipAuth
}
versions
- go run github.com/99designs/gqlgen version?
v0.17.16
- go version?
go1.19.1 darwin/amd64
for future travellers. Here is my hacky solution to this
func skipAuth(graphqlExecutableSchema graphql.ExecutableSchema, r *http.Request) (bool, error) {
var skipAuth bool
var req struct {
Query string `json:"query"`
}
buf, err := ioutil.ReadAll(r.Body)
if err != nil {
return skipAuth, err
}
body := ioutil.NopCloser(bytes.NewBuffer(buf))
copyBody := ioutil.NopCloser(bytes.NewBuffer(buf))
if err := json.NewDecoder(body).Decode(&req); err != nil {
return skipAuth, err
}
r.Body = copyBody
schema := graphqlExecutableSchema.Schema()
parsedQuery, gerr := gqlparser.LoadQuery(schema, req.Query)
if gerr != nil {
return skipAuth, gerr
}
// Retrieve the directive argument value
loop:
for _, op := range parsedQuery.Operations {
for _, sel := range op.SelectionSet {
if field, ok := sel.(*ast.Field); ok {
objDefinition := field.ObjectDefinition
if objDefinition == nil {
skipAuth = false
break loop
}
for _, f := range objDefinition.Fields {
if field.Name != f.Name {
continue
}
schemaQuery := schema.Query
if schemaQuery != nil {
if info := schema.Query.Fields.ForName(f.Name); info != nil {
if skipAuthDirective := info.Directives.ForName("skipAuth"); skipAuthDirective != nil {
skipAuth = true
break loop
}
}
}
schemaMutation := schema.Mutation
if schemaMutation != nil {
if info := schema.Mutation.Fields.ForName(f.Name); info != nil {
if skipAuthDirective := info.Directives.ForName("skipAuth"); skipAuthDirective != nil {
skipAuth = true
break loop
}
}
}
}
}
}
}
return skipAuth, nil
}
func Middleware(next http.Handler, graphqlExecutableSchema graphql.ExecutableSchema) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if ok, _ := skipAuth(graphqlExecutableSchema, r); ok {
next.ServeHTTP(w, r)
return
}
// other programs goes here
})
}