LoginSignup
1
0

More than 1 year has passed since last update.

Nuxt Basic AuthによるBadRequest(400)の解消

Last updated at Posted at 2021-12-29

はじめに

関係者で保有するデータを見える化するため、Nuxt.jsを利用したプロトタイプ開発を実施していました。
コンテンツ開放前は、Basic認証をかけて関係者のみに展開できるようにするため、
Nuxt.jsに簡単にBasic認証をかけられる「nuxt-basic-auth-module」を利用したのですが、
諸所の条件が重なり、データ表示の際にBad Request(400)が発生するようになってしまいました。

解決することができたので、それらの過程をまとめてみました。

実現しようとしていたこと

当初は下図のイメージで、プロトタイプを構築しようとしていました。
データはDBは利用せず、S3に保存し、API Gateway経由で取得するようにしています。
S3は公開領域に保存せず、API Gatewayのキー情報をヘッダーに入れて取得するようにしています。

初期インフラ構成.png

nuxt-basic-auth-moduleの導入

Nuxt.jsアプリケーションやAPI Gateway経由でS3のファイルでアクセスする処理は、下記のような感じで出来上がったため、早速 nuxt-basic-auth-moduleを導入することとしました。

const response = await $axios.$get($config.API_GATEWAY_URL) {
  headers: {"x-api-key": $config.X_API_KEY}
}
return {
  data: response.data,
}

nuxt-basic-auth-moduleは下記の記事を参考に導入しました。

あっさりと導入できたので、お客様に展開するため、アプリケーションのデプロイを実施しました。

ヘルスチェックのエラー対応

いつまでたっても反映されないので、ECSのサービスのログを見てみると下記のようにコンテナ起動・削除が繰り返されていました。

service xxxxxx-service has stopped 1 running tasks: task e68b4001fa904aa187ac793bdd48810a.
080ad5cf-d721-4ab3-b8c7-d3b048f9504f
2021-12-29 17:57:29 +0900
service xxxxxx-service deregistered 1 targets in target-group TG-ecs-xxxxxx
e7892e21-5e35-45c0-8130-7bd0c6ea89d5
2021-12-29 17:57:29 +0900
service xxxxxx-service (port 3000) is unhealthy in target-group TG-ecs-xxxxxx due to (reason Health checks failed with these codes: [401]).
00a9e933-e8d0-4f41-834c-c0894b2eb0a5
2021-12-29 17:52:25 +0900
service xxxxxx-service registered 1 targets in target-group TG-ecs-xxxxxx
c1367a52-62b8-419e-bc13-b76b51464058
2021-12-29 17:51:19 +0900
service xxxxxx-service has started 1 tasks: task e68b4001fa904aa187ac793bdd48810a.
e7ee4c31-86b3-47c4-89a8-f1b8e38fd5c7
2021-12-29 17:51:08 +0900

(省略)

service xxxxxx-service has stopped 1 running tasks: task cd0081685db84991ac02e88dd85269db.
f6f36466-6821-471b-acfa-a2e4c2e13d53
2021-12-29 17:45:07 +0900
service xxxxxx-service deregistered 1 targets in target-group TG-ecs-xxxxxx
53e05ed0-fe70-4618-80e6-8581dc0327ac
2021-12-29 17:45:07 +0900
service xxxxxx-service (port 3000) is unhealthy in target-group TG-ecs-xxxxxx due to (reason Health checks failed with these codes: [401]).
9ffacb22-29ad-4440-84c7-8b8256017fc9
2021-12-29 17:40:10 +0900
service xxxxxx-service registered 1 targets in target-group TG-ecs-xxxxxx
e572bc65-a3ee-42a6-8e3d-417848e3a668
2021-12-29 17:39:13 +0900
service xxxxxx-service has started 1 tasks: task cd0081685db84991ac02e88dd85269db.

原因はヘルスチェックで指定していたパス「/」に対して、Basic認証が動くようになってしまったため、ヘルスチェックが失敗してしまい、コンテナ起動・削除が繰り返されていたのが原因でした。

そこで「healthcheck.vue」というファイルを「pages」ディレクトリに保存し、「/healthcheck」でヘルスチェックを行うように設定することにしました。

特定のパスを Basic認証から除外したい

ただ該当のパスをBasic認証から除外する必要があり、「nuxt-basic-auth-module」でどのようにしたらよいか?を調べることとなりました。

サンプルには記載されていなかったのですが、「match」という設定項目があり、
下記の通り記載されています。

match
type: String(regex literal) | Function
required: false
The target path. This allows you to set up basic authentication that is limited to routes that match regular expression literals or where the function returns true.

なるほど正規表現で指定すればいいんですね。
ということで「/healthcheck」を除外(否定)する正規表現を記載して設定してみたのですが、
なかなかうまく動きません。(おそらく正規表現の記載方法が間違っているのかなとは思います。)

もう1つ「function」で指定できるとのことでしたので、以下の functionを記載して、設定してみました。

  // Basic Authentication
  basic: {
    name: 'xxxxxxxx',
    pass: 'xxxxxxxx',
    enabled: 'true',
    match: req => {
      return req.url !== '/healthcheck' 
      && req.url.indexOf('_nuxt') == -1
      && req.url.indexOf('_loading') == -1
    }
  },

※_nuxtや_loadingも結果として必要で、入れないとBasic認証に引っかかって、アプリケーションが動作しませんでした。

これでヘルスチェックも成功するようになり、無事デプロイ完了しました。

後は動作確認をしたら、お客様に展開するだけです。

ファイルサイズが大きすぎた(S3 Signed URLの導入)

アプリケーションを表示しようとしたところ、データ取得のAPIで「500エラー(Internal server error)」
調べていたら、Lambdaではレスポンスのサイズ制限があるとのことでした。

下記の記事を参考に、S3のPre-Signed URLを導入し、解決を図ることにしました。

■S3のPre-signed URLを利用したアクセス

// Pre-signed URLの取得
const url = await $axios.$get($config.API_GATEWAY_URL) ~
  headers: {"x-api-key": $config.X_API_KEY}
})
// S3ファイルの取得
const response = await $axios.$get(url)

return {
  data: response.data,
}

Bad Request (400)の発生と解消

500エラーは解消したのですが、今度は下記のようにBad Request(400)エラーが発生するようになってしまいました。

BadRequest.png

原因探るのには結構時間がかかってしまったのですが、Basic認証が成功した後のリクエストでは、「Authentication」ヘッダーが自動で設定されていて、S3の署名付きURLでアクセスした場合、エラーとなってしまっているのが原因でした。

そのためS3の署名付きURLの呼び出し前で「Authentication」ヘッダーを削除して、アクセスするようにしたところ、無事アクセスができるようになりました。

// Pre-signed URLの取得
const url = await $axios.$get($config.API_GATEWAY_URL) ~
  headers: {"x-api-key": $config.X_API_KEY}
})
// Authenticationヘッダーの削除
delete $axios.defaults.headers.common.authorization
// S3ファイルの取得
const response = await $axios.$get(url)

return {
  data: response.data,
}

ようやくお客様にプロトタイプを展開できそうです。

でも今後フィードバックが返ってくるので、これからが本番です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0