ぬまろぐ

←戻る

クロスドメインでの非同期通信(ajax)でのBASIC認証設定方法まとめ

2021/03/07

クロスドメインへ非同期通信(ajax)に対してBASIC認証をかける際に考慮する点や設定方法を検証・整理したので書いておきたいと思います。

一応、slideshareにもまとめてみました。

AJAXのBASIC認証検証結果 from Shintaro Mizunuma

1. 通常のBASIC認証フロー(画面リクエスト時など)

通常のBASIC認証フローは以下のようになります。検証はnginxで行ったため、nginxの設定例で書いています。

img
  1. ブラウザがサーバにリクエストを行う
  2. サーバはステータスコード「401 Unauthorized」とレスポンスヘッダ「Authorization: Basic」を付けて応答する
  3. ブラウザにユーザ名、パスワード入力のダイアログが表示される
  4. ブラウザはリクエストヘッダに「Authorization: Basic [ID:PW]」を付けて再度リクエストを行う

これを行うためのnginxの設定は以下ようになります。BASIC認証のIDとPWは「.htpasswd」ファイルを作り書き込みます。(パスワードはハッシュ化する)

# nginx.conf serverディレクティブやlocationディレクティブに設定
auth_basic "realm text";
auth_basic_user_file .htpasswd;
# .htpasswdファイル パスワードはSHA-1などでハッシュ化したもの
name1:password1
name2:password2:comment
name3:password3

2. 同一ドメインへの非同期通信(ajax)でのBASIC認証

非同期通信(ajax)のリクエスト先でBASIC認証をかける時のnginxの設定やフローは先ほどの画面のBASIC認証と同じになります。

画面から非同期通信(ajax)を行った際に、ブラウザに認証ダイアログが表示されます。

3. 別ドメインへの非同期通信(ajax)でのBASIC認証(プリフライトなし)

別ドメインへの非同期通信(ajax)でBASIC認証を行う際は、いくつか追加の設定が必要になります。

ajaxを行うクライアントのjavascriptではxhrのwithCredentialsをtrueに設定する必要があります。これを行わないと別ドメインへのcookieや認証情報の送信が許可されずBASIC認証も許可されません。

サーバ側はCORS用のレスポンスヘッダを返す設定が必要になります。nginxのadd_headerはBASIC認証の401レスポンス時にはalwaysオプションを付けないとヘッダが付与されないため注意が必要です。

add_header 'Access-Control-Allow-Methods' 'GET,OPTIONS,PUT,DELETE' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Headers' 'Authorization,User-Agent,Keep-Alive,Content-Type,accept,origin' always;
add_header 'Access-Control-Allow-Origin' 'https://myhost.com' always;

auth_basic "test";
auth_basic_user_file .htpasswd;

フローは以下のようになり、同一ドメインのときと同様です。

img

4, 別ドメインへの非同期通信(ajax)でのBASIC認証(プリフライトあり)

プリフライトありのajax通信の時はフローが少しことなり、これを考慮した設定が必要になります。フローは以下のようになります。

  1. ブラウザは最初にプリフライト(OPTIONリクエスト)をサーバに送る
  2. サーバはCORS用のヘッダをつけて200 OKレスポンスを返す
  3. ブラウザは非同期リクエストを送る
  4. サーバはCORS用ヘッダを付けて401 Unauthorizedレスポンスを返す
  5. ブラウザは画面に認証ダイアログを表示する
  6. ブラウザはリクエストヘッダに「Authorization: Basic [ID:PW]」を付けて再度リクエストを行う
img

注意点は、プリフライト(OPTIONリクエスト)は401 Unauthorizedで返却してはいけないというところです。ブラウザはプリフライトではBASIC認証を行わないため、もしプリフライトで401が返却されるとエラーとなります。

そのため、nginxの設定は以下のようになります。

add_header 'Access-Control-Allow-Methods' 'GET,OPTIONS,PUT,DELETE' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Headers' 'Authorization,User-Agent,Keep-Alive,Content-Type,accept,origin' always;
add_header 'Access-Control-Allow-Origin' 'https://myhost.com' always;

if ($request_method = 'OPTIONS') {
    return 200;
}

auth_basic "test";
auth_basic_user_file .htpasswd;

以上で非同期通信時のBASIC認証のフローや設定の考慮点は全てになります。