Merge pull request #1 from exstake/feature/jwt-authentication-on-graphql-controller
add jwt authentication on graphql controller
This commit is contained in:
4
Gemfile
4
Gemfile
@@ -15,12 +15,12 @@ gem "webpacker", "~> 5.0"
|
|||||||
gem "bootsnap", ">= 1.4.4", require: false
|
gem "bootsnap", ">= 1.4.4", require: false
|
||||||
|
|
||||||
gem "devise"
|
gem "devise"
|
||||||
gem "devise-bootstrap-views", "~> 1.0"
|
gem "devise-bootstrap-views"
|
||||||
gem "devise-i18n"
|
gem "devise-i18n"
|
||||||
|
|
||||||
gem "administrate"
|
gem "administrate"
|
||||||
gem "graphql"
|
gem "graphql"
|
||||||
gem "tailwindcss-rails"
|
gem "tailwindcss-rails"
|
||||||
|
gem "httparty"
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem "dotenv-rails"
|
gem "dotenv-rails"
|
||||||
|
|||||||
10
Gemfile.lock
10
Gemfile.lock
@@ -113,6 +113,9 @@ GEM
|
|||||||
graphql (1.12.14)
|
graphql (1.12.14)
|
||||||
graphql_playground-rails (2.1.0)
|
graphql_playground-rails (2.1.0)
|
||||||
rails (>= 5.1.0)
|
rails (>= 5.1.0)
|
||||||
|
httparty (0.18.1)
|
||||||
|
mime-types (~> 3.0)
|
||||||
|
multi_xml (>= 0.5.2)
|
||||||
i18n (1.8.10)
|
i18n (1.8.10)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
jbuilder (2.11.2)
|
jbuilder (2.11.2)
|
||||||
@@ -143,12 +146,16 @@ GEM
|
|||||||
mini_mime (>= 0.1.1)
|
mini_mime (>= 0.1.1)
|
||||||
marcel (1.0.1)
|
marcel (1.0.1)
|
||||||
method_source (1.0.0)
|
method_source (1.0.0)
|
||||||
|
mime-types (3.3.1)
|
||||||
|
mime-types-data (~> 3.2015)
|
||||||
|
mime-types-data (3.2021.0704)
|
||||||
mini_mime (1.1.0)
|
mini_mime (1.1.0)
|
||||||
mini_portile2 (2.6.1)
|
mini_portile2 (2.6.1)
|
||||||
minitest (5.14.4)
|
minitest (5.14.4)
|
||||||
momentjs-rails (2.20.1)
|
momentjs-rails (2.20.1)
|
||||||
railties (>= 3.1)
|
railties (>= 3.1)
|
||||||
msgpack (1.4.2)
|
msgpack (1.4.2)
|
||||||
|
multi_xml (0.6.0)
|
||||||
nio4r (2.5.8)
|
nio4r (2.5.8)
|
||||||
nokogiri (1.12.1)
|
nokogiri (1.12.1)
|
||||||
mini_portile2 (~> 2.6.1)
|
mini_portile2 (~> 2.6.1)
|
||||||
@@ -304,11 +311,12 @@ DEPENDENCIES
|
|||||||
bootsnap (>= 1.4.4)
|
bootsnap (>= 1.4.4)
|
||||||
capybara
|
capybara
|
||||||
devise
|
devise
|
||||||
devise-bootstrap-views (~> 1.0)
|
devise-bootstrap-views
|
||||||
devise-i18n
|
devise-i18n
|
||||||
dotenv-rails
|
dotenv-rails
|
||||||
graphql
|
graphql
|
||||||
graphql_playground-rails
|
graphql_playground-rails
|
||||||
|
httparty
|
||||||
jbuilder (~> 2.7)
|
jbuilder (~> 2.7)
|
||||||
listen (~> 3.3)
|
listen (~> 3.3)
|
||||||
pg (~> 1.1)
|
pg (~> 1.1)
|
||||||
|
|||||||
12
app/controllers/concerns/authenticable.rb
Normal file
12
app/controllers/concerns/authenticable.rb
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Authenticable
|
||||||
|
def current_auth
|
||||||
|
@current_auth ||= Auth::Authenticate.new(bearer_token).profile
|
||||||
|
end
|
||||||
|
|
||||||
|
def bearer_token
|
||||||
|
pattern = /^Bearer /
|
||||||
|
header = request.headers["Authorization"]
|
||||||
|
header.gsub(pattern, "") if header&.match(pattern)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,17 +1,16 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class GraphqlController < ApplicationController
|
class GraphqlController < ApplicationController
|
||||||
# If accessing from outside this domain, nullify the session
|
include Authenticable
|
||||||
# This allows for outside API access while preventing CSRF attacks,
|
|
||||||
# but you'll have to authenticate your user separately
|
protect_from_forgery with: :null_session
|
||||||
# protect_from_forgery with: :null_session
|
|
||||||
|
|
||||||
def execute
|
def execute
|
||||||
variables = prepare_variables(params[:variables])
|
variables = prepare_variables(params[:variables])
|
||||||
query = params[:query]
|
query = params[:query]
|
||||||
operation_name = params[:operationName]
|
operation_name = params[:operationName]
|
||||||
context = {
|
context = {
|
||||||
# Query context goes here, for example:
|
current_user: current_admin_user, # || current_auth.current_user,
|
||||||
current_user: current_admin_user,
|
current_auth: current_auth,
|
||||||
}
|
}
|
||||||
result = XStakeSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
|
result = XStakeSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
|
||||||
render(json: result)
|
render(json: result)
|
||||||
@@ -22,7 +21,6 @@ class GraphqlController < ApplicationController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Handle variables in form data, JSON body, or a blank value
|
|
||||||
def prepare_variables(variables_param)
|
def prepare_variables(variables_param)
|
||||||
case variables_param
|
case variables_param
|
||||||
when String
|
when String
|
||||||
@@ -34,7 +32,7 @@ class GraphqlController < ApplicationController
|
|||||||
when Hash
|
when Hash
|
||||||
variables_param
|
variables_param
|
||||||
when ActionController::Parameters
|
when ActionController::Parameters
|
||||||
variables_param.to_unsafe_hash # GraphQL-Ruby will validate name and type of incoming variables.
|
variables_param.to_unsafe_hash
|
||||||
when nil
|
when nil
|
||||||
{}
|
{}
|
||||||
else
|
else
|
||||||
|
|||||||
20
app/services/auth/auth0_client.rb
Normal file
20
app/services/auth/auth0_client.rb
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Auth
|
||||||
|
class Auth0Client
|
||||||
|
class << self
|
||||||
|
def find_profile(token)
|
||||||
|
Profile.new(user_profile_attributes(token))
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_profile_attributes(token)
|
||||||
|
HTTParty.get(
|
||||||
|
"https://#{ENV["AUTH_DOMAIN"]}/userinfo",
|
||||||
|
headers: {
|
||||||
|
"Content-Type" => "application/json",
|
||||||
|
"Authorization": "Bearer #{token}",
|
||||||
|
}
|
||||||
|
).with_indifferent_access
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
14
app/services/auth/authenticate.rb
Normal file
14
app/services/auth/authenticate.rb
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Auth
|
||||||
|
class Authenticate
|
||||||
|
attr_reader :jwt_token
|
||||||
|
|
||||||
|
def initialize(jwt_token)
|
||||||
|
@jwt_token = jwt_token
|
||||||
|
end
|
||||||
|
|
||||||
|
def profile
|
||||||
|
Auth0Client.find_profile(jwt_token)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
15
app/services/auth/profile.rb
Normal file
15
app/services/auth/profile.rb
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
module Auth
|
||||||
|
class Profile
|
||||||
|
attr_reader :id, :email
|
||||||
|
|
||||||
|
def initialize(attributes)
|
||||||
|
@id = attributes[:sub]
|
||||||
|
@email = attributes[:email]
|
||||||
|
end
|
||||||
|
|
||||||
|
def customer
|
||||||
|
@customer ||= Customer.find_by(email: email, auth_id: id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user