Sails+Passport+Passport-Google-OAuthでOAuthをする場合

##SailsとPassportでOAuth認可する
***
**※追記：利用バージョンを書き忘れていたので追記**
###バージョン
*Sails v0.9.9
*Passport.js v0.2.0
*passport-google-oauth v0.1.5
***
ここではGoogleのAPIを使ってOAuthしてみる。プロトコルのバージョンはOAuth2.0。Passportのストレテジはpassport-google-oauthでOAuth2Strategyを使う。

###コントローラ
```js:AuthController.js
/**
 * AuthController
 *
 * @module      :: Controller
 * @description	:: A set of functions called `actions`.
 *
 *                 Actions contain code telling Sails how to respond to a certain type of request.
 *                 (i.e. do stuff, then send some JSON, show an HTML page, or redirect to another URL)
 *
 *                 You can configure the blueprint URLs which trigger these actions (`config/controllers.js`)
 *                 and/or override them with custom routes (`config/routes.js`)
 *
 *                 NOTE: The code you write here supports both HTTP and Socket.io automatically.
 *
 * @docs        :: http://sailsjs.org/#!documentation/controllers
 */
var passport = require('passport');
module.exports = {
  login: function(req,res){
    res.view();
  },
  authenticate: function(req,res){
    passport.authenticate('google',{scope:['https://www.googleapis.com/auth/userinfo.profile']})(req,res);
  },
  authcallback: function(req,res){
    passport.authenticate('google', {failureRedirect: 'login',successRedirect:'/message/success'})(req,res);
  },
  logout: function(req,res){
    req.logout();
    res.send('logout');
  },
  /**
   * Overrides for the settings in `config/controllers.js`
   * (specific to AuthController)
   */
  _config: {}
};
```
loginからauthenticateを呼出し、Googleの認可フローにリダイレクト後、authcallbackにコールバックされて戻ってくる。

###api/services/passport.js
```js:passport.js
// api/services/passport.js
// This code is a little dirty. TODO: refactor this code for easy to read.
 
var passport = require('passport'),
GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
 
passport.serializeUser(function (user, done) {
  done(null, user.userId);
});
 
passport.deserializeUser(function (id, done) {
  User.findOne({userId:id}).done(function(err, user){
    if(err){
      done(null,null);
    } else {
      done(null,user);
    }
  });
});
passport.use(new GoogleStrategy({
	       clientID:"",
	       clientSecret: "",
               callbackURL: "http://localhost:1337/auth/authcallback"
            },
            function(accessToken,regreshToken,profile,done) {
	       process.nextTick(function(){
	           User.findOne({userId:profile.id}).done(function(err, user){
				   if(err){
                                     return done(null,err);
                                   } else {
                                     if(!user){
                                       User.create({userId:profile.id, userName:profile.name}).done(
                                                    function(err,createUser){
                                                       if(err){
                                                         return done(null,err);
                                                       } else {
							 return done(null,createUser);
						       }
                                                    });
                                     } else {
				       return done(null,user);
				     }
                                   }
				});
               });
}));
```
認可後の処理を含むフロー。セッションのデータのシリアライズとデシリアライズもここに記述。新しいユーザならユーザ情報をローカルのDBにも保存する。

###config/config_passport.js
```js:config_passport.js
// config/passport.js
// initialize passport as middleware
 
var passport = require('passport'),
GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
 
module.exports = {
  express: {
    customMiddleware: function(app) {
      app.use(passport.initialize());
      app.use(passport.session());
    }
  }
};
```
midllewareとしてinitializeするための記述。Sailsのアプリ起動時に呼び出されて初期化される。

###views/auth/login.ejs
```html:login.ejs
// views/auth/login.ejs
<h2>Google Login</h2>
<form action="/auth/authenticate" method="post">
<div><input type="submit"></div>
</form>
```
authenticateを呼び出しているだけ。

あとは必要に応じてpolicies.jsで認可前アクセスの制御（AuthControllerのメソッドは認可前でもアクセス可にしておく）とapi/policies内に配置するコードで認可前認可後のセッションのチェックのコードを追記する。