mBaaSはスマートフォンアプリ向けのサービスですが、バックエンドとしてだけ見ると、何もアプリだけに限りません。一般的にサーバサイドで必要になる認証、データベース、ファイルストレージなどmBaaSを使うことで管理が不要になります。
そこで今回はJavaScript SDKを使ってWebサービスを構築する方法について紹介します。まず最初に問題になりそうな認証の行い方です。
なぜ認証が問題になるのか
通常、JavaScript SDKを使っているのは個人の端末になります。そのため、認証データ(セッションIDなど)は個人の端末にしか保存されません。しかし、サーバサイドで使う場合にはサーバサイドがユーザに変わって認証を行うようなものです。その結果、セッションIDがサーバ側に返ってきます。
このセッションIDはユーザの認証情報になります。そのため、セッションIDが漏洩したり、書き換えられることで他人のデータにアクセスできる可能性があります。そうならないために、多くは別途セッションを保存しておくデータベースを用意しますが、mBaaSを使っているのにデータベースを用意するのは面倒でしょう。
そうした問題を解決できるのがJSON Web Tokenになります。
JSON Web Tokenとは?
JSON Web TokenはURLセーフなトークンです。URLセーフというのはURLに使えない文字を含まない、という意味です。基本はJSONですが、Base64でエンコードすることでURLセーフにしています。そして、情報を改ざんできないという特徴があります。情報を基に署名を行っており、情報を改ざんすると署名が変わるので検知できるという仕組みです。
JSON Web Tokenは全部で3つのパートからなります。それぞれのパートをドット(.)でつないだのがJSON Web Tokenです。
- ヘッダー
- ペイロード
- 署名
の3つで、ペイロードに情報を入れます。サーバ側ではWebブラウザから送られてきたJSON Web Tokenが改ざんされていないことが確認できれば、そこに入れられた情報(セッションIDなど)を安心して利用できます。
Node.js向けには jsonwebtoken
というライブラリが使えます。
サービスを作る
では実際に使ってみましょう。今回はNode.js + Expressで作っていきます。Expressのベースを生成するExpress generatorが便利です。
$ npm install -g express-generator
まずベースを生成します。
$ express ncmb_server
そしてライブラリをインストールします。
$ cd ncmb_server/ $ npm install
ライブラリをインストール
まずはJavaScript SDKをインストールします。
$ npm install ncmb --save
後は前述のJSON Web Tokenをインストールします。
$ npm install jsonwebtoken --save
ログイン処理を作る
今回はあらかじめユーザを作成してあることとします。 routes/sessions.js
にてログイン処理を作ります。ログイン画面は GET /sessions で表示します。
var express = require('express'); var router = express.Router(); var jwt = require('jsonwebtoken'); /* GET users listing. */ router.get('/', function(req, res, next) { res.render('sessions/index'); });
テンプレート(Jade)は次のようになります。
extends ../layout block content h1 ログイン form(action="/sessions",method="post") p ユーザID input(type="text",name="userId",placeholder="ユーザID") p パスワード input(type="password",name="password",placeholder="") p button(type="submit") ログイン```
ログインは POST /sessions にて行います。 app = module.parent.exports
でExpressのアプリケーションインスタンスを受け取れるのがコツです。今回はJSON Web Tokenを24時間の有効期限でセットしています。jwt.sign で署名を作成します。その署名をCookieにセットします。
router.post('/', (req, res, next) => { const app = module.parent.exports; const ncmb = app.get('ncmb'); const secret = app.get('secret'); ncmb.User .login(req.body.userId, req.body.password) .then(user => { console.log(user); const userHash = { userName: user.userName, objectId: user.objectId, mailAddress: user.mailAddress, sessionToken: user.sessionToken } var token= jwt.sign(userHash, secret, { expiresIn: '24h' }); res.cookie('token', token); res.redirect('/'); }) });
トークンですが、以下のような文字列になります。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyTmFtZSI6InRlc3QiLCJvYmplY3RJZCI6IkVhZ05uaHQzTXY1eDlLVUsiLCJtYWlsQWRkcmVzcyI6bnVsbCwic2Vzc2lvblRva2VuIjoiVHpTajA2c3l2RWVnUEk1bU1yajgwdGNEdyIsImlhdCI6MTUyMzYwMjA0OSwiZXhwIjoxNTIzNjg4NDQ5fQ.Tt5Y4lxiE13RqQIsukGUXowXlzkT32JDBLT14sFef7w
このトークンをドットで分割した時、二つ目の文字列がペイロードになります。
{ "userName":"test", "objectId":"EagNnht3Mv5x9KUK", "mailAddress":null, "sessionToken":"TzSj06syvEegPI5mMrj80tcDw", "iat":1523602049, "exp":1523688449 }
この文字列を改変したりするとJSON Web Tokenとして使えなくなります。
データを登録する
ではこのトークンを使ってデータ登録処理を行います。この時には Cookieから送られる文字列が使えます。 jwt.verify
を使ってJSON Web Tokenの検証とデコードができます。エラーにならなければ改ざんされていないということなので、そのまま使えます。
ncmb.sessionToken にセッショントークンを当てはめれば認証状態としてサーバにアクセスできます。
router.post('/', (req, res, next) => { const token = req.cookies.token; const app = module.parent.exports; const ncmb = app.get('ncmb'); try { const json = jwt.verify(token, app.get('secret')); ncmb.currentUser = new ncmb.User(json) ncmb.sessionToken = json.sessionToken; const Todo = ncmb.DataStore('Todo'); const acl = new ncmb.Acl; acl .setUserReadAccess(ncmb.currentUser, true) .setUserWriteAccess(ncmb.currentUser, true); const todo = new Todo; todo .set('txt', req.body.txt) .set('acl', acl) .save() .then(todo => { res.redirect('/todos'); }) } catch (e) { } });
このようにしてACLにも対応したデータを保存したり、表示できます。
まとめ
今回のコードはNCMBMania/server_demo: mBaaSをサーバサイドで使うデモです。にアップロードしてあります。認証データの取り回しができれば、後はWebブラウザで使うJavaScript SDKとほとんど使い方は変わらないでしょう。
サーバサイドでmBaaSを使うことで、アプリとのデータ共有であったり、サーバサイドでありがちな機能をあらかじめ実装しておいた状態で使える、さらにデータベースを用意しないでいいといったメリットがあります。ぜひお使いください!