Edited at

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がユーザディレクトリとしてベンダーロックイン、スケーラビリティの観点からかなり良いんじゃないかと思います。