はじめに
Passport.js v0.6.0を利用している方向けの内容です
Passport.js v0.6.0ではログインをすると、デフォルト設定の場合、それ以前のSession情報が破棄されてしまいます。
SAML認証自体は問題なく出来るのですが、例えば、ログインしていない状態でURLにアクセスすると、「流入元のURLの情報がログイン処理中に失われて、流入元URLにリダイレクトできない」です。
Passport.js v0.4.1 を利用して実装している「ローカル環境のみで完結するSAML SSOサンプル(node, express, saml-idp利用)」 で紹介されているサンプルコード(の routes/auth.ts)では、ログインしていない状態でURLにアクセスをすると、下記の流れで処理が進むと思いますが、v0.6.0では同様の挙動をしてくれません。
- 認証チェックのロジックに入り、
req.session.requestUrl
にアクセスしたURLをセットする - ログイン画面に遷移し、ログインをする
- POST /login/callback が呼ばれて、
req.session.requestUrl
にセットされたURLにリダイレクトする
// <省略>
const authModule = passport.authenticate('saml', { failureRedirect: '/login/fail' });
// <省略>
/**
* idpで認証後のコールバックURL
* ・この時点で、認証されたユーザ情報が「req.user」にセットされる
* ・リクエスト時のURLにリダイレクトする
*/
router.post('/login/callback', authModule, (req, res) => {
if ((req as any).session) {
res.redirect((req as any).session.requestUrl);
delete (req as any).session.requestUrl;
} else {
res.redirect('/');
}
});
// <省略>
/**
* 認証チェック
* ・全てのReact側からの通信に対して、認証チェックを行う
* ⇒認証されていない場合は、saml認証を行う
*/
router.all(['/*'], (req, res, next) => {
// <省略>
console.log(`${req.url} Not authenticated. Redirect to /login`);
// リクエストされたurlをセッションに保存してから、idpへ認証を依頼
(req as any).session.requestUrl = req.url;
return authModule(req, res, next);
});
サンプルコード をv0.6.0を利用して動かすと、3の処理で req.session.requestUrl
の値が undifined
になってしまい、流入元のURLにリダイレクトできません。
これは1の処理のセッションと3の処理のセッションが異なっていることが要因です。
(=sessionIDが違う。 req.sessionID
を各処理でconsole.logで出力することで確認できます。)
対応策
Passport.js v0.6.0で v0.4.1と同様の挙動にするには、 passport.authenticate
のオプションに keepSessionInfo: true
を設定すればよいです。
const authModule = passport.authenticate(
'saml',
{
failureRedirect: '/login/fail',
keepSessionInfo: true, // これ!!
}
);