Help us understand the problem. What is going on with this article?

Amazon API GatewayにBasic認証をかける方法

はじめに

ちょっとしたテスト用のAPIをAmazon API Gatewayで作ったのですが、あんまり外部公開はしたくない…でもガッチガチなセキュリティが必要なほど重要なものでもない…
というわけでBasic認証をかける方法を調べたメモです。
いくつかハマリポイントがありました。

大まかな流れ

API GatewayでBasic認証する大まかな流れ。

  1. API Gatewayのオーソライザーに認証をするLambda関数を指定する。
  2. オーソライザーのIDソースにauthorization (header)を設定する。
  3. API Gatewayの「ゲートウェイのレスポンス」の401レスポンスにWWW-Authenticateヘッダーを追加する。
  4. メソッドリクエストの設定でオーソライザーを指定する。

Lambda関数の作成

AWS Lambdaのダッシュボードから関数を作成します。Rubyが好きなのでここではRubyを選択しています。

名前は適当に、実行ロールは「基本的な Lambda アクセス権限で新しいロールを作成」でOKです。

lambda-authorizer-basic-auth
require 'aws-sdk-kms'
require 'base64'

def lambda_handler(event:, context:)
  if basic_auth(event)
    # Basic認証で認可する場合は次のようなIAMポリシーを返す
    {
      'principalId': 'user',
      'policyDocument': {
        'Version': '2012-10-17',
        'Statement': [
          {
            'Action': 'execute-api:Invoke',
            'Effect': 'Allow',
            'Resource': event['methodArn']
          }
        ]
      }
    }
  else
    # 認可しない場合は例外を送出する
    raise 'Unauthorized'
  end
end

# Basic認証する適当メソッド
def basic_auth(event)
  # ユーザー名とパスワードはLambdaの環境変数に暗号化して保存してある。
  user = Aws::KMS::Client.new.decrypt({ ciphertext_blob: Base64.decode64(ENV['user']) }).plaintext
  password = Aws::KMS::Client.new.decrypt({ ciphertext_blob: Base64.decode64(ENV['password']) }).plaintext

  # event['headers']['authorization']にBasic認証の認証情報が入っている
  auth_header = event['headers']['authorization']

  # 適当に認可
  auth_str = 'Basic ' + Base64.strict_encode64("#{user}:#{password}")
  auth_header == auth_str
end

オーソライザーのドキュメントはこちらにあります。
ドキュメントの例がNode.jsだったので、Rubyの場合は認可しない場合に何を返せばいいのかわからず悩んだのですが、raiseしてエラーを送出すれば良いようです。
(Node.jsのcallbackの引数をちゃんと調べればわかることでした)

オーソライザーの設定

API Gatewayのダッシュボードから次のようにオーソライザーを設定します。

ポイントはIDソースにauthorizationヘッダーを設定することです。これによりブラウザなどからのBasic認証を伴うリクエストをLambda関数に渡すことができます。

image.png

401レスポンスの設定

Basic認証なしでAPIにアクセスした場合に401エラーを返しますが、そのときにBasic認証が必要であることをブラウザなどに伝える必要があります。これがないと、ブラウザのBasic認証ダイアログなどが出ないので困ります。

「ゲートウェイのレスポンス」→「権限がありません」→レスポンスヘッダーにWWW-Authenticate、値に'Basic'を追加します。静的な値の場合は''で囲む必要があります。

image.png

メソッドの設定

あとはBasic認証をかけたいAPIメソッドの設定で、認可の方法に先のオーソライザーを指定するだけです。

image.png

その他

オーソライザーやレスポンス、メソッドの設定を変えた後はデプロイしないとAPIに反映されないので気をつけましょう(n敗)

おわりに

AWS勉強中なのですが色々わからない概念が多くてつらいです。
記事のコード中のコメントにIAMロールを返すとかもっともらしく書いてありますが、それが何かはよくわかっていない模様。

今回はブラウザからAPIにアクセスする必要があったのでBasic認証にしましたが、アプリケーションなどからアクセスする場合はAPIキー使ったほうが楽だと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした