-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Authenticate non-root fields #243
Comments
Hey @janosrusiczki! You are not doing something wrong, this is the correct behavior of the gem as commented in
This was done for performance reasons at first as not doing this would mean we have to run the authentication code for every field and that might happen a lot of times in a single query. I'll try to run some benchmarks and see what's the actual effect of enabling the feature for nested fields |
I agree, it's probably a big overhead to check all the fields. Maybe a global flag in an initializer: granular authentication on / off? Or some way to enable it on each type? Default being disabled. |
We need to think about this a bit more, but I kind of feel we might not want to allow this unless it has a very low impact to performance. For a more granular access control I think it would be better to use an authorization gem. This one was kind of an inspiration for this project, but I don't see much activity on the project. Anyway, there might be a fast way to handle the scenario where nested fields don't set the |
I give a look at graphql-guard gem. It does not work on the newer version of ruby-graphql, and since all the interface it was written on top of was removed, I think it'll not be updated to work with. It was written on top of Maybe instead of adding this on top of this gem, what about building one, not-opinative gem, giving a way for the developer to implement his own "guard" method, other than the default one, that I think should be as simple as "authenticated", but on the field, something like |
That's a good idea. That might be a good alternative. graphql-guard definitively looks abandoned. But I still have to look into supporting this in this gem. As I said before, maybe performance won't be too affected if we check every level of the query (at least for presence of the |
I think that I have a hint about why it's abandoned looking into this doc Ps: no end code down there, just some ideas about it for anyone that comes here Doing something like this should work. Configure module Types
class BaseField < GraphQL::Schema::Field
include ::GraphqlDevise::FieldAuthentication
attr_accessor :authorize
def initialize(*args, authorize: true, **kwargs, &block)
super(*args, **kwargs, &block)
@authorize = authorize
end
def authorized?(obj, args, ctx)
authorize.instance_of?(Proc) ? authorize.call(obj, args, ctx) : authorize
end
argument_class Types::BaseArgument
end
end And it gives you some power to use it like: class Authorize < ApplicationService
def initialize(action, restrict: false)
@action = action
@restrict = restrict
@authorizer = YourAuthorizerClass.new
end
def call
proc do |obj, _args, ctx|
user_allowed?(ctx[:current_resource], obj)
end
end
private
attr_accessor :action, :restrict, :authorizer
def user_allowed?(user, record)
authorizer.authorize?(user, record, action, restrict:)
end
end module AuthTypes
ADMIN = ::Authorize.call(:any, restrict: true)
READ = ::Authorize.call(:show, restrict: false)
CREATE = ::Authorize.call(:create, restrict: false)
UPDATE = ::Authorize.call(:update, restrict: false)
LIST = ::Authorize.call(:index, restrict: false)
DESTROY = ::Authorize.call(:destroy, restrict: false)
end module Types
class UserType < Types::BaseObject
field :id, ID, null: false, authorize: AuthTypes::READ
field :name, String, null: true, authorize: AuthTypes::READ
field :title, String, null: true, authorize: AuthTypes::READ
field :email, String, null: false, authorize: AuthTypes::READ
field :encrypted_password, String, null: false, authorize: AuthTypes::ADMIN
field :reset_password_token, String, authorize: AuthTypes::ADMIN
field :reset_password_sent_at, GraphQL::Types::ISO8601DateTime, authorize: AuthTypes::ADMIN
field :remember_created_at, GraphQL::Types::ISO8601DateTime, authorize: AuthTypes::ADMIN
field :created_at, GraphQL::Types::ISO8601DateTime, null: false, authorize: AuthTypes::ADMIN
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false, authorize: AuthTypes::ADMIN
end
end |
Is it possible to authenticate non-root fields?
After some hurdles I managed to set this gem up with graphql 2.0.14. I got to the point where I set
authenticate_default: false
in my main schema and if I setauthenticate: true
on one of the root fields in QueryType I'm getting an error if I want to access it while not being authenticated. However if I addauthenticate: true
to one of the non-root fields it doesn't seem to have any effect.In my case I have:
I can access id without being authenticated.
Is it possible to have this type of granular authentication? If yes, what am I doing wrong?
The text was updated successfully, but these errors were encountered: