SocketStreamにeveryauthでTwitterログインさせる
SocketStream にFacebookやTwitterなどのソーシャルアカウントでのログインをする時には、everyauth がオススメです。
ソーシャルログイン系のライブラリでは、他にPassportとかもあるんですが、
Easy authentication - use a backend database or authenticate against Facebook Connect, Twitter, etc using Everyauth
と、socketstreamのReadmeに記載があり、ドキュメントにもEveryauthの使い方が紹介されています。
また、機能的にもeveryauthで特に問題ないので(Passportとの違いがよくわからん)、今回はEveryauthを使ってログインさせてみましょう。
※CoffeeScriptで書いてるので読めない人はコンパイルしてね
app.coffee
※SocketStreamは言語にcoffeeを指定($ socketstream new -c hoge)しても app.js しか出力してくれないので、手作業で app.coffee にデコンパイルしてあります。
#app.coffee http = require('http') ss = require('socketstream') everyauth = require('everyauth') config = require('config') mongoose = require('mongoose') #connect to mongodb mongoose.connect 'mongodb://localhost/HOGE' ss.session.store.use('redis') ss.publish.transport.use('redis') #Define a single-page client called 'main' ss.client.define 'main', view: 'app.html' css: ['app.less'] code: ['libs/jquery.min.js', 'libs/underscore-min.js', 'libs/backbone-min.js', 'app'] tmpl: '*' #Serve this client on the root URL ss.http.route '/', (req, res)-> res.serveClient('main') User = require('./server/rpc/models/user').User #twitter oauth everyauth.twitter .consumerKey(config.Twitter.consumerKey) .consumerSecret(config.Twitter.consumerSecret) .findOrCreateUser((session, accessToken, accessTokenSecret, twitterUserMetaData)-> #str_id でユーザーを検索 User.findOne({id_str: twitterUserMetaData.id_str}, (err, user)-> #create new user user = new User id_str: twitterUserMetaData.id_str if !user #create or update user name and icon user.name = twitterUserMetaData.screen_name user.icon - twitterUserMetaData.profile_image_url #save user user.save() session.user = user.toObject() session.save() true ) true ) .redirectPath('/') #Code Formatters ss.client.formatters.add(require('ss-coffee')) ss.client.formatters.add(require('ss-less')) #Use server-side compiled Hogan (Mustache) templates. Others engines available ss.client.templateEngine.use(require('ss-hogan')) #Minimize and pack assets if you type: SS_ENV=production node app.js if ss.env is 'production' ss.client.packAssets() #for everyauth ss.http.middleware.prepend(ss.http.connect.bodyParser()) ss.http.middleware.append(everyauth.middleware()) #Start web server server = http.Server(ss.http.middleware) server.listen(3000) #Start SocketStream ss.start(server)
まず、everyauthをrequireします。
everyauth = require('everyauth')
当然、「$ npm install everyauth」や package.json に書いておく必要があります。
次に、順番は前後しちゃいますが、以下が結構重要です。
#for everyauth ss.http.middleware.prepend(ss.http.connect.bodyParser()) ss.http.middleware.append(everyauth.middleware())
bodyParser
は、connect の bodyParser で、レスポンスボディをパースしてくれるみたいです。
たぶんcallback時のURLをパースしてモニョってくれるんだと思います。
まずはそれを prepend に指定する必要があると。
で、 apeend にeveryauth.middleware() を指定する事で、認証用のURLが有効になります。
everyauth.twitter .consumerKey(config.Twitter.consumerKey) .consumerSecret(config.Twitter.consumerSecret) .findOrCreateUser((session, accessToken, accessTokenSecret, twitterUserMetaData)-> #(略 ) .redirectPath('/')
最後にこの部分で、twitterによる認証処理をモニョモニョします。
モニョモニョっていっても、consumerKey / consumerSecretKey を指定するのと、oauth認証ができたあとのcallback処理を書く感じです。
最初に書いた例では、mongoose(MongoDBのORM的なの)のUserモデルからid_strが一致するユーザがいるかどうかを確認して、いれば名前とアイコンをアップデート、新規ユーザであれば新しくオブジェクトをMongoDBに保存しています。
そのうえで、セッションにユーザデータを保存しているという感じです。
rpc内での利用
app.coffee で認証とセッションデータの作成だけやっておいて、rpc内で使う時は、
#server/rpc/user.coffee exports.actions = (req, res, ss) -> req.use('session') get_name: => res req.session.user.name
みたいな感じで、req.user('session')
しておけば、各アクションの中で req.session
で参照する事ができます。
クライアントサイドからの呼び出し
クライアントサイドで、
ss.rpc 'user.get_name', (user_name) -> console.log(user_name)
みたいな感じで呼び出せば、ユーザ情報をクライアントサイドへ渡す事ができます。
ログインURL
everyauthの仕様で、ログインURLは決まっています。
もちろんオプションで変更させる事もできるのですが。
#everyauthのreadmeに載ってるログインURLとコールバックURLの変更(facebookの場合) everyauth.facebook .entryPath('/auth/facebook') #<-認証URL .callbackPath('/auth/facebook/callback')
ようするに、http://example.com/auth/ソーシャルサービス名 がログインURLで、その後に /callback を足したものがコールバックURLとしてデフォルトで設定されています。
なので、/auth/twitter に対してリンクを貼れば、そこがTwitterログインのURLになる、といった感じです。
知らないと、「everyauth設定したけど結局どこでログインすりゃいいのさ!?」ってハマっちゃいます(体験談
まとめ
HTTPのセッションとWebsocketのセッションは本来別物なのですが、そこはSocketStreamが良い感じにしてくれますし、OAuthについてはトークンを設定する以上の事は何もせずともeveryauthがよしなにやってくれますし、TwitterとFacebookとなんとかと、、、と、複数のログイン手段を、超簡単に用意する事ができます。
SocketStreamの日本語情報が世の中に少なかったりするので、ちょいちょい書いていこうかなと思い、第1弾としてeveryauthとの連携を紹介しました。