Rust on Lambda AuthorizerでサーバサイドLINE認証してみた

2022.08.04

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Lambda Authorizer付きのRustで書いたLambda関数を使ってLINE認証をしてみました。
CDKとTypescriptを使ってインフラ構築を行い、RustでLambda関数を作りました。LambdaではLambda Authorizerとして認証を行なった後、Lambda関数上でLINE認証を実行します。
処理の流れは次のようになります。

  1. ユーザーがAPIを呼び出すと、API Gatewayがリクエストを受け取ります
  2. API Gatewayは認証用のLambda関数(Lambda Authorizer)を呼び出します。
  3. 認証が成功すると、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行目
  • LINE_CLIENT_IDとLINE_CLIENT_SECRETには、LINE Developersで作成したChannelからコピーしたものを貼り付けます。
  • LAMBDA_AUTH_TOKENには、トークンとして好きな文字列を入れます。
  • S3_DOMAINには、ReactをデプロイしたS3のエンドポイントを入れます。
  • LAMBDA_ENDPOINTには、Lambdaのエンドポイントを入れて、末尾に/api/v1/をつけます。
  • (デプロイ先のURLを環境変数に設定します。一度デプロイした後、デプロイ先のエンドポイントを確認して環境変数に入れてから、再度デプロイする必要があります。おそらくクロススタック参照などを使えば良いのですが、今回はそこまでしませんでした。)

    次に各プロジェクトをビルドして、デプロイを実行します。

    cd ./lambda
    ./build.sh
    cd ../front
    npm run install
    npm run build
    cd ../cdk
    npm run install
    cdk deploy --all
    

    以上でデプロイの作業が完了します。

    感想

    開発用にlocalstackを使おうとしてエラーが出たり、cors設定が間違っていて詰まったり、Rustの文法が分からなくて詰まったり、いろいろ難しかったです。その分かなり勉強になったと思います。