2017-10-17 18 views
4

ビルドしているウェブアプリで問題が発生しています。 Webアプリケーションは、角度4のフロントエンドとドットネットコアのRESTfulなapiバックエンドで構成されています。要件の1つは、SSL相互認証を使用してバックエンドへの要求を認証する必要があることです。すなわち、クライアント証明書。TLSクライアント証明書が、ほとんどのブラウザでプリフライトリクエストに含まれないのはなぜですか?

現在、私は、Azureのアプリサービスとしてフロントエンドとバックエンドの両方をホストしていることだし、彼らは別のサブドメイン上にあります。

バックエンドが、私はAzureのアプリケーションサービスのためにそれを行うための唯一の方法であると信じて、このガイドに従うことによって、クライアント証明書を要求するように設定されています https://docs.microsoft.com/en-us/azure/app-service/app-service-web-configure-tls-mutual-auth

フロントエンドがバックエンドに要求を行うとき、私はwithCredentialsを設定trueにあります。[ドキュメントに従う] [1]は、クライアント証明書でも動作するはずです。

XMLHttpRequest.withCredentialsプロパティは、クロスサイトアクセス制御要求は、このようなクッキー、認証ヘッダやTLSクライアント証明書などの資格情報を使用して行われるべきであるかどうかを示すブールです。 withCredentialsを設定しても、同じサイトの要求には影響しません。

フロントエンドから関連するコード:Chromeで

const headers = new Headers({ 'Content-Type': 'application/json' }); 
const options = new RequestOptions({ headers, withCredentials: true }); 

let apiEndpoint = environment.secureApiEndpoint + '/api/transactions/stored-transactions/'; 

return this.authHttp.get(apiEndpoint, JSON.stringify(transactionSearchModel), options) 
    .map((response: Response) => { 
     return response.json(); 
    }) 
    .catch(this.handleErrorObservable); 

これは、要求が行われたときに、ブラウザに証明書をユーザに促し、それがプリフライトリクエストと、すべての作品に含まれます、動作します。

他のすべてのメインブラウザでは、これは当てはまりません。リクエストにクライアント証明書が含まれていない場合、サーバーは接続をシャットダウンするため、Firefox、EdgeおよびSafariはすべてプリフライトリクエストに失敗します。 APIエンドポイントに直接ブラウズ

は、すべてのブラウザは、証明書をユーザーに促しますので、私は、これはほとんどのブラウザは、クライアント証明書とプリフライトリクエストを処理する方法に明示的に関連しているかなり確信しています。

何か問題があったのですか?または、リクエストを行う際に証明書を要求しないことによって、他のブラウザが間違ったことをしていますか?

私はChrome以外のブラウザをサポートする必要があるので、何とか解決する必要があります。

バックエンドに証明書を要求するのではなく、同様の問題が解決されているのを見ました。唯一の問題は、私が実際にAzureアプリケーションサービスでそれを行う方法を見つけていないことです。これは必須か不要かのどちらかです。

どのように私は上に移動することができますか?

+0

リクエストは 'XMLHttpRequest()'または 'fetch()'で行われますか? – guest271314

+0

Chromeでリクエストが正常に機能している場合は、https://stackoverflow.com/posts/46783506/editを使用して質問を編集/更新し、Chrome OPTIONSリクエストのリクエストとレスポンスの詳細を追加してくださいFirefoxの要求に対応しています)と、後続のPOST要求に使用します。 – sideshowbarker

+0

@sideshowbarkerそうです、私は関連するスクリーンキャップで質問を更新しました。 –

答えて

2

https://bugzilla.mozilla.org/show_bug.cgi?id=1019603を参照してください。答えはCORS with client https certificatesです(この同じ問題が以前に報告されていたのを忘れていました...)。

あなたの違いの原因は、Chromeのバグです。私はhttps://bugs.chromium.org/p/chromium/issues/detail?id=775438にバグを提出しました。

問題は、ブラウザがプリフライトリクエストでTLSクライアント証明書を送信しないようにするために、Chromeがこれに関する仕様要件を満たしていないことです。 Chromeの代わりにはTFCクライアント証明書をプリフライトで送信します。

Firefox/Edge/Safariが仕様に準拠しています。プリフライトでTLSクライアント証明書を送信しないでください。


を更新: - あなたのコードからではないPOST要求の質問への編集で追加クローム画面キャプチャはGET要求に対するOPTIONS要求、およびそれに続くGET要求を示しています。したがって、おそらく問題はサーバーがPOST要求を禁止することです。


https://i.stack.imgur.com/GD8iG.pngに示した要求は、ブラウザが自動的にあなたのコード内でPOST要求をしようとする前に、自分自身で送信しCORS preflight OPTIONS requestです。

コードに追加されたContent-Type: application/json要求ヘッダーが、ブラウザがプリフライトを開始する原因となります。OPTIONSリクエスト。

それはそのプリフライトOPTIONSリクエストで任意のcredentialsが含まれたことがないブラウザを理解することが重要です - ので、リクエストがに送信されているサーバーが/api/transactions/own-transactions/からOPTIONS要求のためのいずれかの資格情報/認証を必要としないように設定する必要があります。

しかし、https://i.stack.imgur.com/GD8iG.pngから、サーバーは/api/transactions/own-transactions/へのOPTIONSリクエストを禁止しているようです。たぶんそれは、サーバーが期待する資格情報が要求にないか、または代わりにサーバーがOPTIONS要求をすべて禁止するように構成されているためです。

その結果、ブラウザはプリフライトが失敗したと判断し、すぐそこで停止し、コードからPOSTリクエストを試みることはありません。

https://i.stack.imgur.com/GD8iG.pngに示されていることを考えれば、実際にChromeで予期したとおりに動作する可能性があることはわかりません。特に、プリフライト要求にcredentialsなどのブラウザを送信するブラウザはありません。プリフライトが行われる限り、違いはありません。

+0

投稿していただきありがとうございます。私はCORSのプリフライトリクエストについて理解していると思いました。しかし、私はクロムが実際には犯人であり、プリフライトリクエストにもTLSクライアント証明書を含めることで間違ったことをしていると思います。 サーバーはプリフライトオプションを停止します。これは、取得できないTLSクライアント証明書が必要なためです。私は唯一の解決策は、saimサブドメインからのリクエストを提供するか、OPTIONS要求が実際に応答を得るように、Azureがオプションとしてクライアント証明書を取得する方法を見つけることだと思います。 –

+0

私が使った解決策の1つは、iframeとpostMessageを使うことです。すべてのブラウザで動作します。 – nemke

関連する問題