exAspArk / graphql-guard

Simple authorization gem for GraphQL :lock:
MIT License
472 stars 36 forks source link

type.introspection? || RULES.dig(type, field) doesn't working. #7

Closed ghost closed 6 years ago

ghost commented 6 years ago

If I don't use this:

def self.guard(type, field)
  type.introspection? || RULES.dig(type, field)
end

I can get introspection types without problems which is not good:

Started POST "/graphql" for 172.18.0.1 at 2017-11-26 12:07:58 +0000
Processing by GraphqlController#execute as */*
  Parameters: {"query"=>"\n  query IntrospectionQuery {\n    __schema {\n      queryType { name }\n      mutationType { name }\n      subscriptionType { name }\n      types {\n        ...FullType\n      }\n      directives {\n        name\n        description\n        locations\n        args {\n          ...InputValue\n        }\n      }\n    }\n  }\n\n  fragment FullType on __Type {\n    kind\n    name\n    description\n    fields(includeDeprecated: true) {\n      name\n      description\n      args {\n        ...InputValue\n      }\n      type {\n        ...TypeRef\n      }\n      isDeprecated\n      deprecationReason\n    }\n    inputFields {\n      ...InputValue\n    }\n    interfaces {\n      ...TypeRef\n    }\n    enumValues(includeDeprecated: true) {\n      name\n      description\n      isDeprecated\n      deprecationReason\n    }\n    possibleTypes {\n      ...TypeRef\n    }\n  }\n\n  fragment InputValue on __InputValue {\n    name\n    description\n    type { ...TypeRef }\n    defaultValue\n  }\n\n  fragment TypeRef on __Type {\n    kind\n    name\n    ofType {\n      kind\n      name\n      ofType {\n
        kind\n        name\n        ofType {\n          kind\n          name\n          ofType {\n            kind\n            name\n            ofType {\n              kind\n              name\n              ofType {\n
        kind\n                name\n                ofType {\n                  kind\n                  name\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n", "graphql"=>{"query"=>"\n  query IntrospectionQuery {\n    __schema {\n      queryType { name }\n      mutationType { name }\n      subscriptionType { name }\n      types {\n        ...FullType\n      }\n      directives {\n        name\n        description\n        locations\n        args {\n          ...InputValue\n        }\n      }\n    }\n  }\n\n  fragment FullType on __Type {\n    kind\n    name\n    description\n    fields(includeDeprecated: true) {\n      name\n
    description\n      args {\n        ...InputValue\n      }\n      type {\n        ...TypeRef\n      }\n      isDeprecated\n      deprecationReason\n    }\n    inputFields {\n      ...InputValue\n    }\n    interfaces {\n
 ...TypeRef\n    }\n    enumValues(includeDeprecated: true) {\n      name\n      description\n      isDeprecated\n      deprecationReason\n    }\n    possibleTypes {\n      ...TypeRef\n    }\n  }\n\n  fragment InputValue on __InputValue {\n    name\n    description\n    type { ...TypeRef }\n    defaultValue\n  }\n\n  fragment TypeRef on __Type {\n    kind\n    name\n    ofType {\n      kind\n      name\n      ofType {\n        kind\n        name\n
   ofType {\n          kind\n          name\n          ofType {\n            kind\n            name\n            ofType {\n              kind\n              name\n              ofType {\n                kind\n                name\n                ofType {\n                  kind\n                  name\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n"}}
[active_model_serializers] Rendered ActiveModel::Serializer::Null with GraphQL::Query::Result (12.33ms)
Completed 200 OK in 61ms (Views: 13.7ms | ActiveRecord: 0.0ms)

My GraphQLPolicy:

class GraphqlPolicy

  RULES = {

    Types::QueryType => {
      '*': ->(obj, args, ctx) { ctx[:current_user] } #nil
    }

  }

  def self.guard(type, field)
    RULES.dig(type, field)
  end

end

Why is introspection skipping authorization?

ghost commented 6 years ago

I'm trying also with:

gem 'graphql-guard', github: 'exAspArk/graphql-guard', :branch => 'master'

But if I try with this code:

  def self.guard(type, field)
    type.introspection? || RULES.dig(type, field)
  end

I got this:

Completed 500 Internal Server Error in 158ms (ActiveRecord: 0.0ms)

NoMethodError (undefined method `call' for true:TrueClass):

app/controllers/graphql_controller.rb:11:in `execute'   
exAspArk commented 6 years ago

Hey @johnunclesam,

Thanks for opening the issue!

I got this: Completed 500 Internal Server Error in 158ms (ActiveRecord: 0.0ms) NoMethodError (undefined method `call' for true:TrueClass)

We've made a mistake in https://github.com/exAspArk/graphql-guard/pull/6, should be fixed.

Instead of:

def self.guard(type, field)
  type.introspection? || RULES.dig(type, field)
end

It should be something like:

def self.guard(type, field)
  type.introspection? ? nil : RULES.dig(type, field)
end

I.e. if:

I can get introspection types without problems

If you would like to restrict an access to Schema, you can do something like:

def self.guard(type, field)
  if type.introspection?
    ->(obj, args, ctx) { false } # do not allow getting a schema introspection info
  else
    RULES.dig(type, field)
  end
end

For example, loading GraphiQL will fail with the error:

image

Please let me know if it works for you.

ghost commented 6 years ago

Ok. Thanks for you answer.

1) with type.introspection? ? nil : RULES.dig(type, field) I can still fetch the schema; maybe your misprint?

2) the if method works good.

ghost commented 6 years ago

Can it work also with:

def self.guard(type, field)
  Rails.env.production? && type.introspection? ? ->(obj, args, ctx) { false } : RULES.dig(type, field)
end

??? Right?

semenovDL commented 6 years ago

@johnunclesam, this would work for you:

def self.guard(type, field)
  return RULES.dig(type, field) unless type.introspection?
  Rails.env.production? && ->(obj, args, ctx) { false }
end

or

def self.guard(type, field)
  return RULES.dig(type, field) unless type.introspection?
  ->(obj, args, ctx) { !Rails.env.production? }
end
exAspArk commented 6 years ago

I can still fetch the schema; maybe your misprint?

Yeah, I was referring to "skip authorization" from the README to fix 500. Feel free to contribute and fix it the example in the README if you'd like :)

Can it work also with

@semenovDL @johnunclesam 👍 Any of these approaches may work

ghost commented 6 years ago

https://github.com/exAspArk/graphql-guard/pull/10 done. You can merge, @exAspArk.

exAspArk commented 6 years ago

Thanks! Closing the issue