DynamoDB
Auth0
serverless

Auth0+DynamoDBでユーザ認証基盤を作る

概要

Untitled (1).png

ユーザDBとその認証認可をセットで提供しているサービスはたくさんありますが、一つの問題としてそのサービスにユーザデータがロックインされちゃう問題があります。

それを回避するためには自分たちでユーザDBについてはデータモデリングを行い、認証と認可の部分は別のサービスに任せるというソリューションが最高なんじゃないかと考えて、Auth0とDynamoDBで実現できるか検証しました。結論としてはAuth0のCustom Databaseの仕組みを使うことで出来ました。

Clientアプリケーションの設定

  • Auth0のサイトへアクセスしてまずはアカウントを作成してください
  • Create Applicationからアプリケーションを作ります
    スクリーンショット 2018-10-18 23.24.41.png

  • QuickStartで使いたいテクノロジーを選択します
    スクリーンショット 2018-10-18 23.25.29.png

  • 認証画面のサンプルコードが用意されてるのでそれをダウンロードしましょう

スクリーンショット 2018-10-18 23.25.38.png

  • ダウンロードしたサンプルのapp.jsを開いてdomainやclientIDの設定を行います。
app.js
var webAuth = new auth0.WebAuth({
    domain: 'horike37.auth0.com',
    clientID: 'KJ28cvUXP5OFbmwzc0BK09ce3BKKxRgs',
    redirectUri: window.location.href,
    responseType: 'token id_token',
    scope: 'openid',
    leeway: 60
  });

設定できたら、npm install & npm startを実行して、http://localhost:3000にアクセスします。
すると認証用の画面が表示されているはずです。

スクリーンショット 2018-10-18 23.35.06.png

Custom Databaseの設定

  • Auth0ダッシュボードの左メニューより、Connections > DatabaseからUsername-Password-Authenticationを選択します
    スクリーンショット 2018-10-18 23.37.25.png

  • Custom Databaseのタブを選択するとログインやサインアップ、パスワード変更などを実行するScriptを実装する画面にたどり着きます。まずは最低限のログインとサインアップでDynamoDBのユーザテーブルを使うようにしてみましょう

スクリーンショット 2018-10-18 23.39.46.png

  • DyanoDBには以下のようなuser_idをパーティションキーとするテーブルを定義します スクリーンショット 2018-10-18 23.43.17.png

サインアップの実装

メールアドレスとパスワードをDBに登録します。注:このサンプルコードは動くことしか考えてない、非常に質の低いコードなので本番等ではコピペで使わないでね

function create(user, callback) {
  var aws = require('aws-sdk');

  aws.config.update({
    accessKeyId: '<accessKeyId>',
    secretAccessKey: '<secretAccessKey>',
    region: 'us-east-1'
  });
  var dynamodb = new aws.DynamoDB();


  bcrypt.hash(user.password, 10, function (err, hash) {
    if (err) { return callback(err); }
    var params = {
      Item: {
        "id": {
          S: user.email
        }, 
        "password": {
          S: hash
        },
      }, 
      TableName: "users"
    };
    dynamodb.putItem(params, function(err, data) {
      if (err) return callback(err); // an error occurred
      else return callback(null);           // successful response
    });
  });
}


ログインの実装

入力されたメールアドレスとパスワードをDB渡して検証します。注:このサンプルコードは動くことしか考えてない、非常に質の低いコードなので本番等ではコピペで使わないでね

function login(email, password, callback) {
  var aws = require('aws-sdk');
  aws.config.update({
    accessKeyId: '<accessKeyId>',
    secretAccessKey: '<secretAccessKey>',
    region: 'us-east-1'
  });
  var dynamodb = new aws.DynamoDB();
  var params = {
    Key: {
      "id": {
        S: email
      },
    }, 
    TableName: "users"
  };

  dynamodb.getItem(params, function(err, data) {
   if (err) return callback(err);
    else {
      bcrypt.compare(password, data.Item.password.S, function (err, isValid) {
        if (err) {
          callback(err);
        } else if (!isValid) {
          callback(new WrongUsernameOrPasswordError(email));
        } else {
          callback(null, {
            email: data.Item.id
          });
        }
      });
    }
  });
}

動作確認

では先程の認証画面に戻ってサインアップを試してみます。

スクリーンショット 2018-10-18 23.49.44.png

SIGN UPをクリックするとうまく行ったようです。
スクリーンショット 2018-10-18 23.51.33.png

DynamoDBのデータ確認すると。。うおーーー!!!ちゃんとデータ出来てる!!
スクリーンショット 2018-10-18 23.52.28.png

というわけで、Auth0 + DynamoDBがユーザディレクトリとしてベンダーロックイン、スケーラビリティの観点からかなり良いんじゃないかと思います。