環境
サーバからAPIを叩いてjsonを取ってくるWEBシステム
フロントはJavaScript,jQuery,Riotで組まれている。
認証サーバとAPIサーバが同一(マシンもIPもシステムも)
問題点
JWTにjsonはbase64でエンコードされたものであり、暗号化はされていない。
実装によるがLocalStorageに値を入れる事が多いが、LocalStorageはJSから自由に読み込む事が可能なためXSSにより任意のJSが実行された場合は容易にAccess Tokenを盗む事ができる。
※改ざんされないだけであり、盗まれるたものを利用される恐れはある。
(セッションハイジャック)
解決案
XSS,CSRF対策がしてあるのは大前提
- Access TokenをCookieに格納して"HTTP Only"と"Secure"フラグを付ける。
- Access Tokenやセッショントークンは一定時間ごとに更新される。(30分等)
機構
1. ログイン時にサーバからクライアントに以下の3つを渡す。
クライアント側
| value name | store place | expire | element | Desc |
|---|---|---|---|---|
| Access Token | Session Storage | 30m | user_num,token用乱数 | 必ずJWT |
| Local Key | Local Storage | 30d | user_num,expire,key用乱数 | コストが気になれば通常のjsonでも可 |
| Cookie Key | Cookie | LocalStorage Keyと同じ期間 | user_num,key用乱数 | HTTPOnly,Secure(コストが気になれば通常のjsonでも可) |
※ user_num : user_idと1対1になる乱数(JWTの内容は暗号化されないのでuser_idそのままはまずい)
DB
|value name|Desc|
|---|---|---|---|---|
|User ID|ログイン時に使うid|
|User Num|user_idの代わりにjsonへ含める乱数値|
|Refresh Hash|Sessionが切れた場合に新規Access Tokenを発行する場合の検証につかうHash値|
|Salt|上記ハッシュを生成する際に使ったソルト値|
サーバ側(内部変数)
| value name |
|---|
| Access Token |
| User Num |
| Local Key |
| Cookie Key |
※Refresh Hashの生成方法
-
Local Key+Cookie keyをハッシュ化する。 -
1のハッシュ+ソルトをハッシュ化する。
2.通常(画面遷移なし)利用時
フロントエンド側は定期的にサーバと通信を行っているものとする。
- クライアントは
Access Tokenをサーバへ送信する。(Cookie keyも勝手に送られるけどきにしない。) - サーバは送られてきた
Access Tokenと内部変数のAccess Tokenが一致するかを検証する。異なればログインページへリダイレクトする。 - 一定時間(30分)毎に
Access Token,Local Key,Cookie Keyの3つともクライアントへ送信する。クライアントはそれぞれを格納する。(※この段階ではLocal KeyとCookie Keyは内部変数で保持しているのみで、Refresh Hashは生成・保存されていない。) - クライアントとのセッションが切れた段階でサーバは
Local KeyとCookie Keyを使いサーバはRefresh Hashを生成し、DBへ保存する。
3.ブラウザやタブを閉じた後、再開時
Access TokenはSession Storageに入っているため、ブラウザを閉じたりタブを閉じれば消えてしまうため再度Access Tokenを取得する必要がある。
- クライアントはサーバに対して
Local KeyとCookie keyを送信する。 - サーバはKeyの検証を行う。
- クライアントから送らてきた
Local Key,Cookie keyが改竄されていないかJWTのチェックをする。※KeyがJWTの時のみ -
Local Key,Cookie keyとDBにあるソルトを使いRefresh Hashを生成する。(1のRefresh Hashの生成方法を参照) -
1のRefresh HashとDBのRefresh Hashを突き合わせる。 - 一致すれば新規の
Access Tokenを発行する。異なれば ログイン画面へリダイレクトする。
- クライアントから送らてきた
- サーバはクライアントに
Access Token,Local Key,Cookie Keyを送信する。 - クライアントは新規の3つをそれぞれ格納する。
4.その他
- JWTのjsonが改ざんされていた場合
-
Access TokenがなくLocal Key,Cookie keyもない場合 -
Local Key,Cookie keyの期限が切れている
これらはすべてログイン画面へリダイレクトさせる。