Skip to main content

graphql_jwt_pundit_integration

🔑 Secure GraphQL Resolvers with JWT Authentication and Pundit​

For API-first Rails apps, authenticating and authorizing GraphQL resolvers at the same time maintains a unified permission model. Decode the JWT in your GraphQL controller, set current_user, and pass a Pundit context into the schema. Use authorize! in resolvers to guard individual fields or mutations.

# app/controllers/graphql_controller.rb
class GraphqlController < ApplicationController
def execute
token = request.headers['Authorization']&.split(' ')&.last
context = { current_user: authenticate_jwt(token) }
result = MySchema.execute(
params[:query], variables: params[:variables], context: context
)
render json: result
end

private

def authenticate_jwt(token)
payload = JWT.decode(token, Rails.application.secrets.jwt_secret)[0]
User.find(payload['sub'])
rescue JWT::DecodeError
nil
end
end
# app/graphql/types/query_type.rb
field :project, Types::ProjectType, null: false do
argument :id, ID, required: true
end
def project(id:)
project = Project.find(id)
Pundit.authorize(context[:current_user], project, :show?)
project
end

This pattern ensures every GraphQL field is wrapped in Pundit’s authorization checks while centralizing token decoding logic.