You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
docuseal/app/controllers/oauth/register_controller.rb

64 lines
1.8 KiB

# frozen_string_literal: true
module Oauth
class RegisterController < ActionController::API
THROTTLE_LIMIT = 20
THROTTLE_WINDOW = 1.hour
rescue_from JSON::ParserError do
render json: { error: 'invalid_client_metadata' }, status: :bad_request
end
def create
return render_error('rate_limited', :too_many_requests) if throttled?
body = JSON.parse(request.raw_post.presence || '{}')
redirect_uris = Array(body['redirect_uris']).map(&:to_s).reject(&:blank?)
return render_error('invalid_redirect_uri') if redirect_uris.empty?
return render_error('invalid_redirect_uri') unless redirect_uris.all? { |u| valid_redirect?(u) }
app = Doorkeeper::Application.create!(
name: body['client_name'].to_s.presence || "MCP client #{SecureRandom.hex(4)}",
redirect_uri: redirect_uris.join("\n"),
scopes: 'mcp',
confidential: false
)
render json: {
client_id: app.uid,
client_id_issued_at: app.created_at.to_i,
client_secret_expires_at: 0,
redirect_uris: redirect_uris,
grant_types: %w[authorization_code refresh_token],
response_types: %w[code],
token_endpoint_auth_method: 'none',
scope: 'mcp',
client_name: app.name
}, status: :created
end
private
def render_error(code, status = :bad_request)
render json: { error: code }, status: status
end
def valid_redirect?(uri_str)
uri = URI.parse(uri_str)
return true if uri.scheme == 'https'
return true if uri.scheme == 'http' && %w[localhost 127.0.0.1 ::1].include?(uri.host)
false
rescue URI::InvalidURIError
false
end
def throttled?
key = "dcr:#{request.ip}"
count = Rails.cache.increment(key, 1, expires_in: THROTTLE_WINDOW)
count && count > THROTTLE_LIMIT
end
end
end