Initial commit
This commit is contained in:
93
app/api/v2/management/jwt_authentication_middleware.rb
Normal file
93
app/api/v2/management/jwt_authentication_middleware.rb
Normal file
@@ -0,0 +1,93 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'stringio'
|
||||
|
||||
module API::V2
|
||||
module Management
|
||||
class JWTAuthenticationMiddleware < Grape::Middleware::Base
|
||||
extend Memoist
|
||||
mattr_accessor :security_configuration
|
||||
|
||||
def before
|
||||
return if request.path == '/api/v2/management/swagger'
|
||||
|
||||
check_request_method!
|
||||
check_query_parameters!
|
||||
check_content_type!
|
||||
payload = check_jwt!(jwt)
|
||||
|
||||
env['rack.input'] = StringIO.new(payload.fetch(:data, {}).to_json)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def request
|
||||
Grape::Request.new(env)
|
||||
end
|
||||
memoize :request
|
||||
|
||||
def jwt
|
||||
JSON.parse(request.body.read)
|
||||
rescue StandardError => e
|
||||
raise Exceptions::Authentication, \
|
||||
message: 'Couldn\'t parse JWT.',
|
||||
debug_message: e.inspect,
|
||||
status: 400
|
||||
end
|
||||
memoize :jwt
|
||||
|
||||
def check_request_method!
|
||||
return if request.post? || request.put?
|
||||
|
||||
raise Exceptions::Authentication, \
|
||||
message: 'Only POST and PUT verbs are allowed.',
|
||||
status: 405
|
||||
end
|
||||
|
||||
def check_query_parameters!
|
||||
return if request.GET.empty?
|
||||
|
||||
raise Exceptions::Authentication, \
|
||||
message: 'Query parameters are not allowed.',
|
||||
status: 400
|
||||
end
|
||||
|
||||
def check_content_type!
|
||||
return if request.content_type == 'application/json'
|
||||
|
||||
raise Exceptions::Authentication, \
|
||||
message: 'Only JSON body is accepted.',
|
||||
status: 400
|
||||
end
|
||||
|
||||
def check_jwt!(jwt)
|
||||
begin
|
||||
scope = security_configuration.fetch(:scopes).fetch(security_scope)
|
||||
keychain = security_configuration
|
||||
.fetch(:keychain)
|
||||
.slice(*scope.fetch(:permitted_signers))
|
||||
.each_with_object({}) { |(k, v), memo| memo[k] = v.fetch(:value) }
|
||||
result = JWT::Multisig.verify_jwt(jwt, keychain, security_configuration.fetch(:jwt, {}))
|
||||
rescue StandardError => e
|
||||
Rails.logger.error "ManagementAPI check_jwt error: #{e.inspect}"
|
||||
raise Exceptions::Authentication, \
|
||||
message: 'Failed to verify JWT.',
|
||||
debug_message: e.inspect,
|
||||
status: 401
|
||||
end
|
||||
|
||||
unless (scope.fetch(:mandatory_signers) - result[:verified]).empty?
|
||||
raise Exceptions::Authentication, \
|
||||
message: 'Not enough signatures for the action.',
|
||||
status: 401
|
||||
end
|
||||
|
||||
result[:payload]
|
||||
end
|
||||
|
||||
def security_scope
|
||||
request.env['api.endpoint'].options.fetch(:route_options).fetch(:scope)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user