はじめに
GraphQLをRails APIで採用する時、認証の有無で処理を分ける方法です。
実装方法は何パターンかあるみたいですが、自分はオペレーション名を見て認証が必要なオペレーションが1つ以上存在するなら認証処理を行うようにしました。
GraphQLを利用するためにgem graphql-rubyを利用しています。
こうした
GraphqlControllerのexecuteのcontextを次のように修正
def execute variables = prepare_variables(params[:variables]) query = params[:query] operation_name = params[:operationName] context = { current_user: auth_free?(query) ? nil : current_user } ...
auth_free?()
は認証の有無を判断するメソッド。
オペレーションの名前を確認してbooleanを返す。
current_user
は認証処理を実行して現在のユーザー情報を取得するメソッド。
firebase authのjwt認証などはこのメソッド内で行う。
auth_free?(query)メソッドの中身
def auth_free?(query) if query.blank? # エラー返す処理など ... end parsed_query = GraphQL.parse(query) operations = parsed_query.definitions.select { |q| q.is_a?(GraphQL::Language::Nodes::OperationDefinition) } auth_free_operation_names = %w[ createUser ] operations.each do |operation| return false if operation.selections.find { |o| auth_free_operation_names.exclude?(o.name) } end true end
・最初にクエリーの存在を確認して、存在しなかったらエラーを返すなどを行う。
・GraphQL.parse(query)
で文字列のQueryをパースしてOperationの情報を取得できるようにする。
・パースした結果から対象のGraphQL::Language::Nodes::OperationDefinition
型のオブジェクトを取得する。
・auth_free_operation_names
は、認証を不要とするオペレーション名を配列で保持。
・最後に1つでも認証が必要なオペレーションが存在していたらfalse(認証必要)を返す。
・そうでなければtrue(認証不要)を返す。