ボクココ

個人開発に関するテックブログ

Cookie とログインと remember_me のカラクリ

ども、@kimihom です。

Cookie のすごい基本的なところなんだけど、どハマりしたのでメモ。何時間もかけて原因を探って解決した先に、成長ってのはあるものだな。いい経験をした。

デスクトップアプリで発覚した問題

んでどういう話なのかっていうと、運営している Web サービスで、基本的にログインしたら使い続けられる機能がある。そこで、Electron を使ってデスクトップアプリ化をしようとしていた。

f:id:cevid_cpp:20161109232915p:plain

もともとシングルページっぽいアプリケーションだったので、デスクトップアプリ自体としてうまく機能していた(ログイン周りを除いては)。なぜかデスクトップアプリを起動するたびにログインしなければならない状態になっていた。毎回デスクトップアプリを閉じるたびにログアウトされてしまっているような感じになってしまっていて、相当不便な状態だった。

普段の Web アプリケーションとデスクトップアプリとでは何かが違う。何が違うのか。

デスクトップアプリの Cookie の管理

そもそも Electron はブラウザではないので Cookie に該当するようなことは自分で用意しないといけない。Electron での Cookie は、アプリのデータとして保存されている。 Mac の場合は ~/Library/Application\ Support/myapp-170c4a/Cookies。ここの情報を読み込んで、Web サーバーに Cookie を送っている。

これ自体は全く問題ないのだけど、どうやら Electron で Webアプリを埋め込む場合は、起動の度に別のセッションとしてリクエストが発生するっていう特徴があるようだ。これが今回ハマった原因。

普段私たちが使っているブラウザは、session_idとして Cookie に保存される。Cookie を閲覧するツールを見ると確認できる。

f:id:cevid_cpp:20161109232147p:plain

さて、ここで気になるのが セッションっていうチェック。Cookie には Session Cookie と Persistent Cookie の2つがあるらしく、Session Cookie を指定しているということのようだ。これにより、セッションごとに有効な Cookie であるということを示しているらしい。

Session Cookie はセッションごとにしか存在できない Cookie なので、割とすぐに有効でなくなるとお考えかもしれない。しかし、普通にブラウザを使っている場合は、ページをタブで開き続けていたりセッションを残している場合があったりして、毎回アクセスのたびにログインといった感覚ではなくなる。だから、あまり Session Cookie について意識しなくてもいいような感じになってしまっている。

だけど Electron を使うと、これが顕著に大切になってくる。Electron を起動するたびに Session は入れ替わっているので、Session Cookie として session_idにセッションを保存しただけではダメなのである。

Remember Me の役割

ここでログイン時にたまに見る Remember Me(ログインを保持する) のチェックだ。これは、Session が入れ替わるたびにログインしなおさなければならない問題を解決してくれる。これにチェックを入れると、以下のような Cookie が新しく付与されていることに気づく。

f:id:cevid_cpp:20161109232158p:plain

今度はセッションにチェックが入っていないことが確認できる。先ほどの session_id が異なってログアウト状態になったとしても、この remember_user_token が存在して正しいものであれば session_id を発行し直す的なことをしてくれるようだ。

Electron で Web アプリを埋め込む場合は、この処理が実装されていることが絶対条件になる。

これにより、無事 Electron でもセッションを保持することが可能になった。

終わりに

Cookie と Session ってのは割と Web アプリケーションの基本ではあるが、実装を詳しく見てみると新しい発見があるものだ。今作のブラウザではセッションを割と長く持つ傾向があって、あまり恩恵を感じない ログイン状態を保持するチェック。まさか Electron で埋め込む時に問題に直面するとは思わなかった。

何はともあれ、一つまた成長ができてよかったよかった。