冥冥乃志

ソフトウェア開発会社でチームマネージャをしているエンジニアの雑記。アウトプットは少なめです。

follow us in feedly

Serverless Framework + API Gatewayのアプリケーションに認可を追加する

しばらく合同勉強会の資料準備とシュバルツバース探索など優先順位が高いタスクが積まれていて、手をつけておりませんでしたが、ようやく再開。今回は完全に備忘録的なレベルです。

で、今回は、表題の通り認可を追加してみたいと思います。今回仮で組んだものとは違いますが、最終的な構成のイメージとしては以下の様な感じ。

  1. 認証のプロバイダはアプリケーション外
  2. アプリケーションは認証されていることを前提に個別に認可

つまり、アプリケーションは「その人が本人であること」を確認する責任をおいませんが、「その人がアプリケーションを使う権限をもつこと」を確認する責任はおいます。これが、Serverless SPAであればアプリケーション内に認証プロバイダを持ってもいいと思います。用途次第ということで。

いつもの如く、具体的なコードはこちらのリポジトリをご査収ください。

github.com

CognitoでUserPoolをつくる

とは言え、いくつもサービスが乱立してしまうのもまだ面倒いので、とりあえず認証プロバイダはアプリケーションのリソースに突っ込んで設定、アプリケーションのデプロイと同様にUserPoolもデプロイされる様にしました。認証プロバイダの切り離しはまたあとでやってみたいと思います。肥大しがちなserverless.ymlの分割とかも、プロジェクトのファイル構成の観点からやってみときたいし。

api.wp-kyoto.net

この記事を参考にしました。特に問題なくデプロイまで出来ます。その前にAWS Glueの検証してたのをすっかり忘れてて、違うリージョンみながら「デプロイされねーな」とか思ってた無駄な時間があったくらいです。

なお、記事にはクライアント側が書かれていませんが、私はクライアントのページを用意するのも面倒いので(フロントエンド苦手)、認証用のLambda関数を追加で作りました。sign_upとconfirmとsign_inとrefresh_tokenができる様にしあります。認可という観点でいうと、トークンがあれば作れるはずなので、このあたりがちょっと雑なのは否めません。

ただ、boto3での認証をどのAPIを使えばいいのかいまいちよくわからなかったので、すこしググりました。で、参考にしたのはイカです。Pythonの場合はクライアントサイドで動く訳ではないので、admin_initiate_authを使う、という解釈ですが、あってるのかな?

qiita.com

閑話:UserPool IDについて

認証系のLambda関数から読み出している COGNITO_POOL_CLIENT_ID は作成したUserPoolのIDで、このサンプルを使う場合はデプロイ後に設定しておいてあげる必要があります。その意味で面倒な構成にはなっているのですが、認可の部分のコードをみていただければ分かる通り、認可に必要なのはトークンのみです。そのため、実際に認証プロバイダを切り離して構成する場合にはこのあたりの面倒くささはなくなるとおもいます。

閑話休題:認可を追加する

で、認可。認可ロジックをLambda関数として実装して、対象となるLambda関数のhttpイベントに authorizer を追加すればいいだけでした。

blog.naoshihoshi.com

認可ロジックでは、トークンからユーザ情報にアクセスできるか確認して、エラーがなければ対象となるLambda関数に実行権限を与えるためのJSONオブジェクトを返しています。このJSONオブジェクトをうけてAPI Gatewayがよしなにしてくれる模様。

実行する

認証プロバイダから彫られた認証済みトークンを Authorization ヘッダに渡して、API GatewayのURLを叩くだけです。

curl -H "Authorization: xxx" -d '{"event": "今日はカポエイラに行く", "insight": "首が少し痛いので心配"}' -X POST https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/my-assistant/life_log

Authorization ヘッダがない場合は以下のエラーメッセージが返ります。

{"message":"Unauthorized"}

ちなみに、この認可はAPI Gatewayを通る場合に有効です。認可対象のLambda関数を直接実行する場合( sls invoke コマンドなど)は、認可なしに実行可能となっています。

まとめ

Serverless FrameworkもAPI Gatewayもかなりよしなにしてくれるので、認証・認可周りは非常に楽に開始できるな、と感じました。まあ、認証基盤はそれだけで一大プロジェクトになる要素を持っているのですが、そこまで突っ込んでやるのが目的ではないですし。今回検証したかったことは認可の追加が楽かどうか、という観点なので、その点では知りたいことを確認できた感じです。