mBaaSではアプリケーションキーとクライアントキーを組み合わせて使いますが、もしこの2つのキーが漏洩するとアプリを自由に(アクセス権限がないデータについては)操作できるようになります。コンパイル系のプログラミング言語では安全ですが、Webアプリケーションなどで使うのは難しいかと思います。
そこで今回はJavaScript SDKの署名生成部分をサーバサイドで行うことによってmBaaSを安全に使えるようにしてみたいと思います。以前、JavaScript SDK ver.1については行いましたが、今回はそのver. 2版になります。
変更点
変更するのは以下の3つのファイルです。
- lib/request.js
- lib/signature.js
- lib/ncmb.js
lib/request.js
このファイルはシグネチャ生成メソッドを呼んでいます。シグネチャをサーバサイドで行うと言うことは非同期処理になるということなので、署名生成処理以下をPromiseで行うようにします。
以下のようにすることで、sigという変数に対してシグネチャが入ってくるようにします。
return (this.createSignature || require("./signature").create)( parsedUrl.format(), method, opts.query || "", timestamp, opts.signatureMethod || self.signatureMethod, opts.signatureVersion || self.signatureVersion, opts.fqdn || self.fqdn, opts.apikey || self.apikey, self.clientkey || self.clientkey ).then(function(sig) { : }).catch(function(err) { console.error("Error: "+err); });
lib/signature.js
このファイルは実際にシグネチャを生成しています。変更点としては、
- 文字列ではなくPromiseオブジェクトを返す
- Ajaxで署名生成処理を行う
- リクエストがうまくいったらresolveを呼ぶ
となります。
return new Promise(function(resolve, reject){ : var r = request.post(signature_url); r.send({forEncodeString: sigStr}) .end(function(err, res){ if (err || !res.ok) { return reject(err); }else{ return resolve(res.body.signature); } }); });
今回はmoongift/ncmb-serverを使っています。これは送られた文字列(署名すべき文字列)をクライアントキーを使ってハッシュ化し、それをBase64エンコードしているだけです。
{signature: Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha256'), CLIENT_KEY, json["forEncodeString"])).strip()}.to_json
これでシグネチャが受け取れるようになりました。
lib/ncmb.js
最後にncmb.jsですが、これはクライアントキーがなくともエラーにしないという処理にします。
if(!apikey){ throw new Error("apikey required"); }
また、optionとしてsignature_urlという署名を行うURLを渡せるようにします。
this.signature_url = config.signature_url || null;
試してみる
では実際に試してみます。HTMLは次のようになります。
<script> function onReady() { var application_key = 'c44...00d'; var ncmb = new NCMB(application_key, null, {"signature_url": "http://localhost:4567/sign"}); } document.addEventListener("DOMContentLoaded", onReady, false); </script>
signature_urlは今回の場合、必須になります。2番目のnullはクライアントキーです。後は普通のJavaScript SDKと同じように使えます。
var D = ncmb.DataStore("d"); var d = new D; d.set("test", "hello"); d.save().then(function(d) {console.log(d)});
このようにクライアントキーを隠蔽することで、Webアプリケーションにおいても安全にmBaaSが利用できるようになります。ぜひお試しください。なお、今回のコードはmoongift/ncmb_jsにアップしてあります。