LoginSignup
43
42

More than 5 years have passed since last update.

Claudia.jsでサーバレスアーキテクチャでのOAuth対応を簡単に実装する

Last updated at Posted at 2017-01-22

Claudia.jsはAWS上でAPI GatewayとAWS Lambdaによるサーバレスアーキテクチャを簡単に実現できるNode.js製のフレームワークです。

この際、Facebook, Google, Twitterの用な外部の認証プロバイダから取得したOAuth Access TokenをAPI Gatewayのレイヤーで検証して問題なければ裏のLambdaに投げたいケースが多いと思います。

Claudia.jsを使えばこのような処理が10分もあれば実装できます。

[関連記事]

準備

1. Claudia.jsをインストールします。

npm install -g claudia

2. プロジェクトを作成します。

mkdir [Proj Name] && cd [Proj Name]
npm init
npm install --save claudia-api-builder
npm install --save aws-sdk
npm install --save axios

実装

以下のようなフロントエンドアプリを実装してみます。エラー処理や詳細は割愛します。また、Hello World的なものはCloudia.jsのTutorialをみた方が手っ取り早いです。

  1. フロントエンドアプリがSNSの認証認可APIからOAuthのアクセストークンを取得する。(略)
  2. フロントエンドアプリがアクセストークンを付与してAWS API Gatewayにリクエストを投げる。(略)
  3. AWS API GatewayがSNSの認証認可APIを用いてアクセストークンを検証する。
  4. AWS API GatewayがFaaSの関数を呼び出す。
  5. AWS Lambdaの関数がAWS DynamoDBのテーブルからデータを取得してフロントに返す。

1. カスタム認証の作成

1. カスタム認証用のLambda関数を作成します。

authorizer.jsを作成します。Access Token検証APIを呼び出して有効な場合にAPI実行権限を付与しています。

var axios = require('axios');

//API実行ポリシーの生成
var generatePolicy = function(authToken, methodArn, context) {
    var awsInfo = methodArn.split(':');
    var region = awsInfo[3];
    var accountId = awsInfo[4];

    var apiInfo = awsInfo[5].split('/');
    var restApiId = apiInfo[0];
    var stage = apiInfo[1];
    var method = apiInfo[2];

    //アクセスさせたいリソース
    var resource = 'arn:aws:execute-api:' + region + ':' + accountId + ':' + restApiId + '/' + stage  +'/' + method + '/*';

    return {
        'principalId': authToken.split('-')[0],
        'policyDocument': {
            'Version': '2012-10-17',
            'Statement': [{
                'Effect': 'Allow',
                'Action': ['execute-api:Invoke'],
                'Resource': [resource]
            }]
        }
    };
};

var url = "Access TokenのValidateを行うAPIのURL";

//Tokenの検証とポリシーの付与
exports.auth = function auth(event, context, cb) {
  axios.get(url, {
    params: {
      access_token: event.authorizationToken //HTTP headerのAuthorizationキーの値
    }
  }).then(function (res) {
    var is_valid = true|false; //Tokenの有効性を検証して結果を格納
    if (is_valid) {
       cb(null, generatePolicy(event.authorizationToken, event.methodArn));
    } else {
       cb("Invalid Access Token");
    }
  });
};

2. デプロイ

claudiaコマンドでカスタム認証用のLambda関数をAWSにデプロイします。

claudia create --name custom-authorizer --region us-east-1 --handler authorizer.auth --config claudia-auth.json
  • --name: AWS Lambda上の関数名
  • --region: AWSのリージョン名
  • --handler: カスタム認証の関数名
  • --config: Claudia.js用の設定ファイル名(自動作成されるので任意)
{
  "lambda": {
    "role": "custom-authorizer-executor",
    "name": "custom-authorizer",
    "region": "us-east-1"
  }
}

2. APIとLambda関数の作成

1. APIとLambda関数を作成します。

app.jsという名前にします。

var ApiBuilder = require('claudia-api-builder');
var api = new ApiBuilder();

var AWS = require('aws-sdk');
var dynamodb = new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});

api.registerAuthorizer('apiGatewayAuthorizer', {
  lambdaName: 'custom-authorizer', //AWS Labmda上のカスタム認証の名前
  headerName: 'Authorization' //Tokenを格納するHTTP headerのKey名
});

api.get('/news', function (req) {
  return dynamodb.get({
    TableName:'news',
    Key:{ "id": req.headers.id }
  }).promise().then(function(res) {
    return res.Item;
  });
},{ 
  customAuthorizer: 'apiGatewayAuthorizer' 
});

module.exports = api;

2. デプロイ

claudiaコマンドでAWSにデプロイします。設定ファイルclaudia.jsonが自動で作られます。

claudia create --region us-east-1 --api-module app
{
  "lambda": {
    "role": "myproj-executor",
    "name": "myproj-proj",
    "region": "us-east-1"
  },
  "api": {
    "id": "[PID]",
    "module": "app",
    "url": "[エンドポイントのベースURL]"
  }
}

3. AWS上の設定

  1. AWS DynamoDBのテーブル作成

    newsテーブルを作成する

    aws dynamodb create-table --table-name news --attribute-definitions AttributeName=id,AttributeType=S --key-schema AttributeName=id,KeyType=HASH --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
    

    idキーで検索できるようにレコードを追加。

    aws dynamodb put-item --table-name news --item '{"id":{"S":"id001"}, "content":{"S":"News content 001"}}'
    aws dynamodb put-item --table-name news --item '{"id":{"S":"id002"}, "content":{"S":"News content 002"}}'
            :
    
  2. AWS Lambdaのrole設定

    1. IAM > Roles > [作成したRole名]
    2. Attach Pollicy > AmazonDynamoDBFullAccess
      • 強すぎるので実際は適当なPolicyを作成

4. API実行

  1. PostmanなどでHTTPヘッダのAuthorizationキーにAccess Tokenを、idキーに存在するidを付与して投げます。

    Claudia.jsでAPIを作成した際にはCORSはデフォルトでONになっていますが制限することもできます。

  Controlling Cross-Origin Resource Sharing headers

5. アップデート

  1. スクリプトを修正します。
  2. claudiaコマンドを実行します。

    claudia update --config claudia-auth.json
    claudia update --config claudia.json
    

まとめ

Claudia.jsを利用すれば、外部の認証認可APIを用いたサーバレスアーキテクチャを簡単に実装できます。

より詳細な記事はこちら

以上

43
42
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
43
42