サーバーでユーザー認証にPassportを使用しています。ユーザーがローカルでサインインしているとき(ユーザー名とパスワードを使用)、サーバーはローカルストレージに保存されている[〜#〜] jwt [〜#〜]を送信し、サーバーに送信されます。ユーザー認証を必要とするすべてのAPI呼び出し。
今、私はFacebookおよびGoogleログインもサポートしたいと考えています。 Passportを使い始めて以来、passport-facebookとpassport-google-oauthを使用してPassport戦略を続行するのが最善だと思いました。
私はFacebookについて言及しますが、どちらの戦略も同じように動作します。どちらもサーバールートへのリダイレクトが必要です('/ auth/facebook'および'/ auth/facebook/callback'についても)。このプロセスは成功し、facebook\google IDとトークンを含むユーザーをDBに保存します。
ユーザーがサーバー上で作成されると、JWTが作成されます(facebook\googleから受信したトークンに依存しません)。
... // Passport facebook startegy
var newUser = new User();
newUser.facebook = {};
newUser.facebook.id = profile.id;
newUser.facebook.token = token; // token received from facebook
newUser.facebook.name = profile.displayName;
newUser.save(function(err) {
if (err)
throw err;
// if successful, return the new user
newUser.jwtoken = newUser.generateJwt(); // JWT CREATION!
return done(null, newUser);
});
問題は、作成後にJWTをクライアントに送信する適切な方法が見つからないです。これは、アプリにもリダイレクトする必要があるためです。
app.get('/auth/facebook/callback',
passport.authenticate('facebook', {
session: false,
successRedirect : '/',
failureRedirect : '/'
}), (req, res) => {
var token = req.user.jwtoken;
res.json({token: token});
});
上記のコードアプリのメインページにリダイレクトされますが、トークンを取得できません。 successRedirectを削除すると、トークンは取得されますが、アプリにリダイレクトされません。
そのための解決策はありますか?私のアプローチは間違っていますか?提案があれば十分です。
その問題に対して私が見つけた最良の解決策は、JWTを保持するCookieを使用して予期されたページにリダイレクトすることです。
res.json
を使用すると、json応答のみが送信され、リダイレクトされません。これが、ここで提案されている他の回答では、私が遭遇した問題を解決できない理由です。
だから私の解決策は:
app.get('/auth/facebook/callback',
passport.authenticate('facebook', {
session: false,
successRedirect : '/',
failureRedirect : '/'
}), (req, res) => {
var token = req.user.jwtoken;
res.cookie('auth', token); // Choose whatever name you'd like for that cookie,
res.redirect('http://localhost:3000'); // OR whatever page you want to redirect to with that cookie
});
リダイレクト後、Cookieを安全に読み取り、期待どおりにそのJWTを使用できます。 (実際に、ページが読み込まれるたびにCookieを読み取って、ユーザーがログインしているかどうかを確認できます)
前に述べたように、クエリパラメータとしてJWTを使用してリダイレクトすることは可能ですが、非常に安全ではありません。 Cookieを使用する方が安全であり、明らかに安全ではないクエリパラメータとは異なり、Cookieをさらに安全にするために使用できるセキュリティソリューションがまだあります。
バーの答えに追加します。
Cookieを抽出してローカルストレージに保存し、Cookieを削除して、承認済みページにリダイレクトするランディングコンポーネントを準備しました。
class SocialAuthRedirect extends Component {
componentWillMount() {
this.props.dispatch(
fbAuthUser(getCookie("auth"), () => {
document.cookie =
"auth=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
this.props.history.Push("/profile");
})
);
}
render() {
return <div />;
}
}
適切な解決策は、クライアント側でリダイレクトを実装することです。
単に使用:
app.get('/auth/facebook/callback',
passport.authenticate('facebook', {
session: false,
failureRedirect: '/login'
}), (req, res) => {
res.json({
token: req.user.jwtoken
})
}
)
クライアント側がトークンを受信し、そこからホームページにリダイレクトする場合、ログインが成功しなかった場合は、サーバーによって直接リダイレクトされます。
または、私がするように完全なクライアント側管理に行くことができます:
app.get('/auth/facebook/callback',
passport.authenticate('facebook', {
session: false
}), (req, res) => {
if (req.user.jwtoken) {
res.json({
success: true,
token: req.user.jwtoken
})
} else {
res.json({
success: false
})
}
}
)
success === true
、JWTをLocalStorageに保存します。それ以外の場合は、ログインページにリダイレクトします。