Skip to content

Commit

Permalink
Fix authentication for micropub slice
Browse files Browse the repository at this point in the history
  • Loading branch information
dNitza committed Nov 18, 2023
1 parent ef70633 commit f63df9b
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 0 deletions.
75 changes: 75 additions & 0 deletions slices/micropub/action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,80 @@

module Micropub
class Action < Adamantium::Action
include Deps["logger",
"settings",
not_found_view: "views.not_found",
error_view: "views.error",
sentry: "sentry.client"]

include Dry::Matcher.for(:handle, with: Dry::Matcher::ResultMatcher)
include Dry::Monads[:result]

handle_exception ROM::TupleCountMismatchError => :not_found
handle_exception StandardError => :handle_error

def authenticate!(req, res)
halt 400 if req.env["HTTP_AUTHORIZATION"] && req.params[:access_token]

if Hanami.env == :development || Hanami.env == :test
req.env[:scopes] = verify_token(nil)
return true
end

# Pull out and verify the authorization header or access_token

if req.env["HTTP_AUTHORIZATION"]
header = req.env["HTTP_AUTHORIZATION"].match(/Bearer (.*)$/)
access_token = header[1] unless header.nil?
elsif req.params["access_token"]
access_token = req.params["access_token"]
else
logger.error "Received request without a token"
halt 401
end

req.env[:access_token] = access_token

# Verify the token and extract scopes
req.env[:scopes] = verify_token(access_token)
end

def not_found(_req, res, _exception)
res.status = 404
res.render not_found_view
end

def handle_error(req, res, exception)
raise exception if settings.raise_exceptions

sentry.capture_exception(exception)

res.status = 500
res.render error_view
res.headers["Cache-Control"] = "no-store, max-age=0"
end

def verify_scope(req:, scope:)
req.env[:scopes].include? scope
end

private

def verify_token(access_token)
return %i[create update delete undelete media] if settings.shortcut_key == access_token
return %i[create update delete undelete media] if Hanami.env == :development || Hanami.env == :test

resp = HTTParty.get(settings.micropub_token_endpoint, {
headers: {
"Accept" => "application/x-www-form-urlencoded",
"Authorization" => "Bearer #{access_token}"
}
})
decoded_response = URI.decode_www_form(resp.body).to_h.transform_keys(&:to_sym)

halt 401 unless (decoded_response.include? :scope) && (decoded_response.include? :me)

decoded_response[:scope].gsub("post", "create").split.map(&:to_sym)
end
end
end
2 changes: 2 additions & 0 deletions slices/micropub/templates/error.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
h1 There was an error!
2 changes: 2 additions & 0 deletions slices/micropub/templates/not_found.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
h1 Not Found!
6 changes: 6 additions & 0 deletions slices/micropub/views/error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Micropub
module Views
class Error < View
end
end
end
6 changes: 6 additions & 0 deletions slices/micropub/views/not_found.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Micropub
module Views
class NotFound < View
end
end
end

0 comments on commit f63df9b

Please sign in to comment.