アプリケーションが複数のサードパーティからの情報を必要とする場合がよくあります。 このようなとき、アプリケーションはユーザーに Facebook や Twitter などのアカウントとの“連携”を要求することになるでしょう。
An application may need to incorporate information from multiple third-party services. In this case, the application will request the user to "connect", for example, both their Facebook and Twitter accounts.
これは、ユーザーがすでにアプリケーションから認証されていて、かつサードパーティのアカウントからの許可や連携のみが必要な状況です。 このような認証や権限付与の場合にも Passport を使うことができます。
When this occurs, a user will already be authenticated with the application, and any subsequent third-party accounts merely need to be authorized and associated with the user. Because authentication and authorization in this situation are similar, Passport provides a means to accommodate both.
権限付与は passport.authorize() の呼び出しによって動作します。
権限付与の申請が承諾されれば、ストラテジーの検証用コールバックの req.account に結果がセットされます。
ログインセッションや req.user に影響は及びません。
Authorization is performed by callingpassport.authorize(). If authorization is granted, the result provided by the strategy's verify callback will be assigned toreq.account. The existing login session andreq.userwill be unaffected.
app.get('/connect/twitter',
passport.authorize('twitter-authz', { failureRedirect: '/account' })
);
app.get('/connect/twitter/callback',
passport.authorize('twitter-authz', { failureRedirect: '/account' }),
function(req, res) {
var user = req.user;
var account = req.account;
// ログイン済のユーザーと Twitter アカウントを連携する。
account.userId = user.id;
account.save(function(err) {
if (err) { return self.error(err); }
self.redirect('/');
});
}
);
ルーティングのコールバックでは、req.user と req.account のどちらも利用可能です。
新しく連携されたアカウントはログインユーザーと紐づけられてデータベースに保存されます。
In the callback route, you can see the use of bothreq.userandreq.account. The newly connected account is associated with the logged-in user and saved to the database.
権限付与のストラテジーは、認証で用いたストラテジーと同じものです。
しかし、アプリケーションがサードパーティの認証と権限付与のどちらも必要とする場合もあるでしょう。
この場合では、名前付きストラテジーを使うことで use() の呼び出し時のデフォルトの名前をオーバーライドすることができます。
Strategies used for authorization are the same as those used for authentication.
However, an application may want to offer both authentication and authorization
with the same third-party service. In this case, a named strategy can be
used, by overriding the strategy's default name in the call to use().
passport.use('twitter-authz', new TwitterStrategy({
consumerKey: TWITTER_CONSUMER_KEY,
consumerSecret: TWITTER_CONSUMER_SECRET,
callbackURL: "http://www.example.com/connect/twitter/callback"
},
function(token, tokenSecret, profile, done) {
Account.findOne({ domain: 'twitter.com', uid: profile.id }, function(err, account) {
if (err) { return done(err); }
if (account) { return done(null, account); }
var account = new Account();
account.domain = 'twitter.com';
account.uid = profile.id;
var t = { kind: 'oauth', token: token, attributes: { tokenSecret: tokenSecret } };
account.tokens.push(t);
return done(null, account);
});
}
));
上の例では、twitter-authz ストラテジーが Twitter のアカウント情報を保存するために Account インスタンスを確認または作成していることがわかります。
この結果は req.account に代入されているので、ルーティングハンドラーは認証済のユーザーを連携させることができます。
In the above example, you can see that thetwitter-authzstrategy is finding or creating anAccountinstance to store Twitter account information. The result will be assigned toreq.account, allowing the route handler to associate the account with the authenticated user.
上記のアプローチのデメリットは2つのストラテジーのインスタンスが必要なことです。
One downside to the approach described above is that it requires two instances of the same strategy and supporting routes.
これを避けるためには passReqToCallback オプションを true にセットしてください。
このオプションが有効になると、 第一引数として req が検証用コールバックに渡されるようになります。
To avoid this, set the strategy'spassReqToCallbackoption totrue. With this option enabled,reqwill be passed as the first argument to the verify callback.
passport.use(new TwitterStrategy({
consumerKey: TWITTER_CONSUMER_KEY,
consumerSecret: TWITTER_CONSUMER_SECRET,
callbackURL: "http://www.example.com/auth/twitter/callback",
passReqToCallback: true
},
function(req, token, tokenSecret, profile, done) {
if (!req.user) {
// ログインしていない場合。Twitter アカウントを基にして認証されます。
} else {
// ログインしている場合。Twitter アカウントはこのユーザーと連携されます。
// 連携後も既存のユーザーが渡されるのでログイン状態は変わりません。
// return done(null, req.user);
}
}
));
検証用コールバックに req が引数として渡されると、リクエストの状態を、認証プロセスの組み立てやひとつのストラテジーインスタンスによる認証・権限付与の処理、ルーティングの設定のために使うことができるようになります。
たとえば、ユーザーが既にログインしている場合でも、新しい連携アカウントを紐づけることができます。
また、req にセットされたアプリケーション特有のプロパティ(req.session を含む)も利用できます。
Withreqpassed as an argument, the verify callback can use the state of the request to tailor the authentication process, handling both authentication and authorization using a single strategy instance and set of routes. For example, if a user is already logged in, the newly "connected" account can be associated. Any additional application-specific properties set onreq, includingreq.session, can be used as well.