認証なしでルートを公開できますか?

認証をバイパスするルートを作成する方法はありますか。

これはサードパーティのサービスとの統合に使用されます。
要件は、サービスに URL を提供することです(ヘッダーやペイロードのいずれもサポートされていません)。
以前は “?api_key=…&api_username=” を追加することで可能でしたが、現在は削除されています。

Discourse インスタンスは当社でホストされています。

カスタムプラグインを作成して、ペイロードを受け取り、それに基づいて処理を行うルートを設定する必要があります。ただし、ユーザーを認証できないため、ペイロード自体を認証する方法が必要になる点にご注意ください。

私のルールは、匿名アカウントを許可しないことです。そのため、プラグインのルートにアクセスできません。このシナリオに対応するルートを生成する方法が必要です。

例えば、

  # デフォルトの Rails 3.2 は、空のセッションでリクエストを通過させます
  # ここではより厳格に対応し、セッションと current_user を null 化
  # その後、CSRF 例外を発生させます
  def handle_unverified_request
    # 注: API キーは秘密であり、これが無効であれば CSRF トークンの必要性はなくなります
    unless is_api? || is_user_api?
      super
      clear_current_user
      render plain: "[\"BAD CSRF\"]", status: 403
    end
  end

このフロー、あるいは認証の全体フローにおいて、パラメータ経由で受け取ったコントローラとアクション(ルート呼び出し時に自動的に設定される)がすべてのチェックをバイパスしてルートを実行できるように通知する仕組みが必要です。

すべての仕組みを完全に理解しているわけではありませんが、匿名アクセスオプションが存在する以上、実現方法はあるはずです。

これにより、必要に応じてペイロードを暗号化できるだけでなく、システムへの一般的な情報更新にも役立ちます。

プラグインを使用して、新しいルートDiscoursePluginRegistry.api_parameter_routesに追加することで、API 認証情報をクエリパラメータとして引き続き渡すことができます:

また、このサイトがログイン必須の場合、カスタムコントローラーに以下の行も追加する必要があります。

skip_before_action :redirect_to_login_if_required

はい。そのメソッドをオーバーライドしてアクションをスキップしてください。成功したら、皆さんにお知らせします。

# デフォルトでは、API 認証情報を送信するヘッダーのみを許可します
  # ただし、一部のシナリオでは URL パラメータ経由で送信することが不可欠なため
  # いくつかの例外を追加する必要があります
  def api_parameter_allowed?
    request_method = @env["REQUEST_METHOD"]&.downcase&.to_sym
    request_format = @env['action_dispatch.request.formats']&.first&.symbol

    path_params = @env['action_dispatch.request.path_parameters']
    request_route = "#{path_params[:controller]}##{path_params[:action]}" if path_params

    if 'm_exposed#endpoint' == request_route && request_method == 'get'
      puts 'Allowed'
      return true
    end

    PARAMETER_API_PATTERNS.any? do |p|
      (p[:method] == "*" || Array(p[:method]).include?(request_method)) &&
      (p[:format] == "*" || Array(p[:format]).include?(request_format)) &&
      (p[:route] == "*" || Array(p[:route]).include?(request_route))
    end
  end

これは将来の git ダーフィスを最小限に抑えるために行いました。

また、私のコントローラー:

# frozen_string_literal: true

class MExposedController < ::ApplicationController

  skip_before_action :redirect_to_login_if_required, raise: false

  def endpoint
    render json: { state: "hello world" }
  end

end

これでエンドポイントはパラメータやヘッダーの認証情報を確認しなくなりました。

提供された API キーを確認し、有効な場合のみアクセスを許可するようにするにはどうすればよいでしょうか?(以前のように動作するように)

@riking @blake ?

requires_login をコントローラーに追加すれば解決すると思います。例については、app/controllers 内の他のコントローラーもご覧ください。

うまくいかなかったようですね :slight_smile:

class MExposedController < ::ApplicationController

  requires_login

  skip_before_action :redirect_to_login_if_required, raise: false

403 Forbidden で完了しました

{"errors":["その操作を行うにはログインが必要です。"],"error_type":"not_logged_in"}

これはプラグイン内で宣言されています。

API 認証情報をクエリパラメータ経由で渡しましたか?もしそうなら、API 認証情報をクエリパラメータで許可するためのバイパスに、そのルートが正しく追加されていない可能性があります。バイパスのロジックをデバッグして、ルートが追加されたかどうかを確認する必要があります。

さて、動作して requires_login なしですべてをバイパスしています。やり方を投稿しました。 Hmm..

認証なしではしか動作しないようです。でも、少なくとも最初の問題は解決しました。