JavaScript アプリから API へのアクセスで発生する CORS エラー

これは私にとって良い回答なのですが、ヘッダーベースの認証が機能しないため、フォームで実装しようとしており、CSRF の問題にも直面しています。解決策はありますか?API を使って新しいトピックを作成しようとしています。

サポートを提供するためには、さらに情報が必要です。ヘッダーベースの認証を使用しようとしている方法を示すコードスニペットを共有していただけますか?

私が直面している問題は、ヘッダーベースの認証で呼び出しを行おうとするたびに、受け入れられるヘッダーが常に「User-Api-Key」と「User-Client-Id」であり、「Api-Key」と「Api-Username」ではないことに起因しています。そのため、CORSエラーが発生します。ユーザーベースのキーは不要だと考えています。単に新しいトピックを作成するための簡単な認証付きリクエストを試みているだけです。「User-Api-Key」を使用しようとすると、403エラーが発生します。

以下はサンプルコード(Angular TypeScript)ですが、他のセットアップでも同様のはずです。

    createNewTopic(postBody: any) {
        let url = "myserver.com/posts.json";
        let CATEGORY_ARTICLES = 6;
        let topicContent = `
          <p>Some content
        </p>
        <p>Did that work?</p>
        `;
        let post = {
          "title": "Tdk Test 1",
          "raw": topicContent,
          "category": CATEGORY_ARTICLES,
          "target_usernames": "tdekoekkoek",
          "archetype": "",
          "created_at": new Date()
        }
        let headers = new HttpHeaders()
          .set("Accept", "application/json")
          .set("User-Api-Key", DISCOURSE_API_KEY)
          .set("User-Key", "system")
          .set("Content-Type", "application/x-www-form-urlencoded")
        let options = {headers: headers};
        return this.http.post(url, post, options);
      }

user-api-keyuser-client-idは、完全に異なる認証方法です。通常の API キーではこれらのヘッダーは機能しません。正しいヘッダー名(api-keyapi-username)を使用した場合、どのような結果になりますか?

サーバーが User-Api-Key を要求しているため、CORS エラーが発生します。OPTIONS 応答で期待されるヘッダーを確認すると、まさにそのようになっています。このフォーラムの他のトピックにも、JavaScript アプリから呼び出した際にユーザーが同様の問題に直面したという事例があります。

ああ、つまりクライアント側の JavaScript アプリケーションからこのリクエストを送ろうとしているのですね?それは多くの理由から許可されていません。例えば、JavaScript アプリのソースコードに管理者 API キーを含めてしまうと、どのユーザーもあなたのフォーラムへの完全な管理者アクセスを得てしまう可能性があります。この件については、こちらの過去のトピックをご覧ください。

はい、それが私が行おうとしていることです。もっと明確にドキュメント化されるべきですね。Discourseを使い始めてからの私の全戦略はそれでした。お手伝いいただきありがとうございます。数日間これと格闘し、ドキュメントを読み続けてきました。現在サーバーレスアプリケーションを構築しているため、アプローチ全体を見直す必要がありますが、Node.jsサーバーにはアクセス可能です。

これは Discourse 固有の制限ではありません。一般的に、ウェブサイトのソースコードに管理者資格情報を含めるのは避けるべきです。

Node.js サーバーから Discourse API を呼び出せるのであれば、それが最も良い解決策でしょう。アプリケーションを完全にクライアントサイドで動作させる必要がある場合は、ユーザー固有の API キーを要求するという選択肢もありますが、その設定ははるかに複雑になります: User API keys specification

正直に言って、CORS を有効にしたクライアントアプリケーションからの API アクセスは非常に一般的で標準的な手法です。これほど安全な方法がないとは信じられません。異なるドメインからアクセスされるホスト型 API を中心とした産業全体が存在しています。ユーザー API によるアクセスについては、作成方法については見たことがありますが、実際の認証情報が何であるかについては明確ではありません。その方法を使用すると、常に 403 権限の拒否エラーが発生します。

私も似た状況にいます。

ユースケースについて少し説明します:

Discourse をバックエンドとして使用し、VueJS でフロントエンドを構築しています。REST API のみを単独で使用することを意図しています。プラットフォーム上の各ユーザーに対してユーザー API キーを作成し、認証には両方のヘッダー(Api-Key と Api-Username)を使用しています。

各ユーザーは当社のサーバーと安全に認証し、その後認証用の Discourse トークンを取得します。その後、このトークン(VueJS フロントエンド内)を使用して API リクエスト(トピックの投稿、投稿の作成、編集など)を送信したいと考えています。

ハードコーディングされたものは何もありません。すべてのトークンは適切な認証後に受け取られます。

問題点:
app.yml で CORS を有効にし、管理設定のセキュリティセクションで設定したにもかかわらず、CORS エラーメッセージが表示されます。

エラー内容:Request header field api-key is not allowed by Access-Control-Allow-Headers

私が経験している CORS エラーメッセージも同じ理由によるものでしょうか?なぜ “Api-Key” と “Api-Username” ヘッダーを使用する際に CORS リクエストがブロックされるのでしょうか?私はおそらくそのユースケースを誤解しているのでしょう。

編集:
私の誤解についての仮説があります。REST API の “Generate an api_key for a user” エンドポイントからユーザー API キーを作成する場合、そのキーには管理者権限が付与されているのでしょうか?それとも、投稿やコメントを行うための単なるユーザーキーなのでしょうか?もしそうであれば、その制限は理解できます。

必要であれば訂正してください。

@david Discourse は、サーバーがセッションシークレットにHMACで署名し、このセッションシークレットが、与えられたセッション内のものを署名するために使用されるということはできませんか?もしそれが盗まれた場合、セッションクッキーやCSRFノンスも同様に盗まれないと仮定します。これは証明書チェーンに似ています。ルートキーをブラウザに配置する必要はありません。

これらは管理者API専用です。私の理解では、JavaScriptクライアントの場合は、上記で言及されているように、User API keys specification を確認する必要があるということです。