diff --git a/app/controllers/api/v1/json_ld_controller.rb b/app/controllers/api/v1/json_ld_controller.rb index 18f3b41f8..704d61b07 100644 --- a/app/controllers/api/v1/json_ld_controller.rb +++ b/app/controllers/api/v1/json_ld_controller.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "faraday" +require "uri" class Api::V1::JsonLdController < Api::BaseController include ActionController::Live @@ -9,6 +10,40 @@ class Api::V1::JsonLdController < Api::BaseController render json: { error: e.to_s }, status: 422 end + before_action :require_user! + + REQUEST_TARGET = '(request-target)' + + def signature(headers) + account = Account.representative + + key_id = ActivityPub::TagManager.instance.key_uri_for(account) + algorithm = 'rsa-sha256' + signed_string = headers.map { |key, value| "#{key.downcase}: #{value}" }.join("\n") + signature = Base64.strict_encode64(account.keypair.sign(OpenSSL::Digest.new('SHA256'), signed_string)) + + "keyId=\"#{key_id}\",algorithm=\"#{algorithm}\",headers=\"#{headers.keys.join(' ').downcase}\",signature=\"#{signature}\"" + end + + def signed_headers(url_string) + if url_string.include?(".well-known") + return {'Accept': 'application/jrd+json'} + end + + url = URI.parse(url_string) + tmp_headers = { + 'Date': Time.now.utc.httpdate, + 'Host': url.host, + 'Accept': 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"', + } + tmp_headers[REQUEST_TARGET] = "get #{url_string.delete_prefix("#{url.scheme}://#{url.host}")}" + additional_headers = { + 'Signature': signature(tmp_headers), + 'User-Agent': Mastodon::Version.user_agent, + } + tmp_headers.merge(additional_headers).except(REQUEST_TARGET) + end + def show url = params[:url] @@ -17,13 +52,12 @@ class Api::V1::JsonLdController < Api::BaseController Thread.new { begin conn = Faraday::Connection.new - conn.options.timeout = 5 - api_response = conn.get(url, nil, {'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams", application/jrd+json'}) + api_response = conn.get(url, nil, signed_headers(url)) max_redirects = 5 while api_response.status == 301 || api_response.status == 302 and max_redirects > 0 do - api_response = conn.get(api_response.headers['Location'], nil, {'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'}) + api_response = conn.get(api_response.headers['Location'], nil, signed_headers(api_response.headers['Location'])) max_redirects -= 1 end diff --git a/app/views/shared/_og.html.haml b/app/views/shared/_og.html.haml index a5d99ae33..c1bef1b3e 100644 --- a/app/views/shared/_og.html.haml +++ b/app/views/shared/_og.html.haml @@ -1,14 +1,14 @@ - thumbnail = @instance_presenter.thumbnail -- description ||= @instance_presenter.description.presence || strip_tags(t('about.about_mastodon_html')) +- description = 'Learn ActivityPub interactively, by seeing protocol interactions visualized in real time' %meta{ name: 'description', content: description }/ -= opengraph 'og:site_name', t('about.hosted_on', domain: site_hostname) += opengraph 'og:site_name', 'ActivityPub Academy - A learning resource for ActivityPub' = opengraph 'og:url', url_for(only_path: false) = opengraph 'og:type', 'website' -= opengraph 'og:title', @instance_presenter.title += opengraph 'og:title', 'ActivityPub Academy' = opengraph 'og:description', description -= opengraph 'og:image', full_asset_url(thumbnail&.file&.url(:'@1x') || asset_pack_path('media/images/preview.png', protocol: :request)) -= opengraph 'og:image:width', thumbnail ? thumbnail.meta['width'] : '1200' -= opengraph 'og:image:height', thumbnail ? thumbnail.meta['height'] : '630' += opengraph 'og:image', full_asset_url(thumbnail&.file&.url(:'@1x') || asset_pack_path('media/images/academy-mascot.webp', protocol: :request)) += opengraph 'og:image:width', thumbnail ? thumbnail.meta['width'] : '500' += opengraph 'og:image:height', thumbnail ? thumbnail.meta['height'] : '573' = opengraph 'twitter:card', 'summary_large_image' diff --git a/dist/nginx.conf b/dist/nginx.conf index 416700370..8347bf1cb 100644 --- a/dist/nginx.conf +++ b/dist/nginx.conf @@ -114,6 +114,27 @@ server { tcp_nodelay on; } + location ^~ /api/v1/json_ld { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Proxy ""; + proxy_pass_header Server; + + proxy_pass http://backend; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection ''; + + proxy_cache off; + proxy_buffering off; + chunked_transfer_encoding off; + + tcp_nodelay on; + } + location ^~ /api/v1/activity_log { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr;