HTTPS(SSL) + session.resave=false + cookie.secure=trueの環境でセッションが使えない?

logoutTitaniumで開発したアプリを本番環境で動かしたときにログインしたあとセッションが持続できない現象を調査したときの覚書。

アプリ環境: Titanium SDK 5.5.2.GA
サーバー環境: CentOS7, nginx 1.8.1, Node.js v4.4.2, express 4.13.4

サーバーのAPIはNode.jsで実装していて、nginxからリバースプロキシしている。

他のプロジェクトはsession.resave=trueにして常に保存するようにしていた。resaveについては公式ドキュメントで。

app.use(session({
  key: APP.Config.cookie.key,
  path: APP.Config.cookie.path,
  secret: APP.Config.cookie.secret,
  cookie: {
    secure: true
  },
  resave: true,
  saveUninitialized: true
}));

今作っているアプリはログインせずにゲストでもいろいろ出来るので、resave=falseにして不要なセッションは作らないようにしてみた。

開発環境では問題なく動作していて、本番環境のHTTPS(SSL)で動かしてみるとセッションが維持できない。

ハマったのはiOSではセッションが維持出来たので(←気のせいだった)、Androidアプリ側の問題かと思っていた。

Cookieを使ったセッションの場合、サーバー側でセッションを保存するとレスポンスヘッダーの「Set-Cookie」に値が入る。

TitaniumだとHTTPClientのonload時にレスポンスヘッダーを見ればCookieに保存するかわかる。

console.log(this.getResponseHeader('Set-Cookie'));

 

nginxのリバースプロキシするときにちゃんとhttpsの通信だというのを指定する必要があった。

location /api/1/ {
    rewrite ^/api/1/(.*)$ /$1 break;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Host $http_host;
    proxy_pass http://127.0.0.1:8880;
    proxy_redirect http:// https://;
}

必要なのはこの2行

proxy_set_header X-Forwarded-Proto https;
proxy_redirect http:// https://;

 

ドキュメントにあるようにNode.js側でtrust proxyも忘れずに

if (app.get('env') === 'production') {
  app.set('trust proxy', 1) // trust first proxy
  sess.cookie.secure = true // serve secure cookies
}

 

 

< Related Posts >