Rust on Lambda AuthorizerでサーバサイドLINE認証してみた
Lambda Authorizer付きのRustで書いたLambda関数を使ってLINE認証をしてみました。
CDKとTypescriptを使ってインフラ構築を行い、RustでLambda関数を作りました。LambdaではLambda Authorizerとして認証を行なった後、Lambda関数上でLINE認証を実行します。
処理の流れは次のようになります。
- ユーザーがAPIを呼び出すと、API Gatewayがリクエストを受け取ります
- API Gatewayは認証用のLambda関数(Lambda Authorizer)を呼び出します。
- 認証が成功すると、API GatewayがLINE認証用のLambda関数を呼び出します。
プロジェクトの構成
扱う言語が2種類あるため、バックエンド(Rust on lambda)、フロント(React + typescript)、インフラ(CDK + typescript)の三つにプロジェクトを分けています。
rust-lambda-auth (ルート)
├── lambda (バックエンド)
├── front (フロント)
└── cdk (インフラ)
VSCodeで開くときは言語が違うため、「lambda」, 「front」, 「cdk」でそれぞれ別々に開きます。
バックエンド(Rust on lambda)
まずバックエンドとしてlambda上で動作する関数を二つ作成しました。一つはLambda Authorizerとして認証を行う関数で、もう一つはLine認証を行う関数です。どちらもRustで書きました。プロジェクトの作成にはcargoを使っています。ビルドするとlambda上で実行可能な形式のファイルを生成してくれます。
ファイル構成は以下のようになっています。
lambda
├── .cargo
| └── config (リンカー設定ファイル)
├── Cargo.lock
├── Cargo.toml
├── build.sh(ビルド用スクリプト)
└── src
├── bin(実行ファイル)
│ ├── lambda_auth_bootstrap.rs
│ └── line_auth_bootstrap.rs
└── lib(ライブラリ)
├── lambda_auth_lib.rs
├── lib.rs
└── line_auth_lib.rs
自分はmacOSを使って、lambda上でも動作できる形でクロスコンパイルをしました。リンカーの設定は .cargo/config に記述しています。
フロント(React + typescript)
次にlambda上に構築した関数を呼び出すフロント側も作成しました。フロント側ではサーバーを通してline認証を行なっていますが、liffアプリ(LINE上で動作するwebアプリ)ではなく、ただのwebアプリとして作成しています。liff SDKも使っていません。
最終的にバックエンドも含め全てデプロイした後で、実行するとまずログインボタンが表示されます。ログインするとaccess_tokenが表示され、「ユーザー情報取得」ボタンを押すと、userIdが表示されます。
通常はフロント側からliff SDKを使ってliff.getAccessToken()やliff.getIDToken()を使ってトークンを取得しますが、今回はサーバーサイドからLINE APIを呼び出してトークンを取得しています。
インフラ(CDK + typescript)
次にCDKを使ってインフラ環境の構築をします。lambdaとAPI GateWayの環境を用意して、フロントから利用できるAPIをデプロイします。
cdk
├── deploy
| └── stack.ts
├── lib
| └──lambda-stack.ts
├── .env
├── cdk.json
├── package.json
└── tsconfig.json
デプロイ方法
デプロイする前に、以下のパスにあるファイルを開いて環境変数を設定する必要があります。
cdk/.env
front/.env
lambda/src/lib/line_auth_lib.rsの31~33行目
(デプロイ先のURLを環境変数に設定します。一度デプロイした後、デプロイ先のエンドポイントを確認して環境変数に入れてから、再度デプロイする必要があります。おそらくクロススタック参照などを使えば良いのですが、今回はそこまでしませんでした。)
次に各プロジェクトをビルドして、デプロイを実行します。
cd ./lambda
./build.sh
cd ../front
npm run install
npm run build
cd ../cdk
npm run install
cdk deploy --all
以上でデプロイの作業が完了します。
感想
開発用にlocalstackを使おうとしてエラーが出たり、cors設定が間違っていて詰まったり、Rustの文法が分からなくて詰まったり、いろいろ難しかったです。その分かなり勉強になったと思います。