日記
SPAをつくることにしたんだけれども、APIの認証をどうしていいのかがいまいちわからない。
APIに状態を持たせるのは良くないということで、セッションを使った認証ではなくJWTを使った認証にチャレンジしてみることにした。
(とはいえ、あんまりそのメリットもよくわかってない。APIで認証のためにセッションを使うのと、tokenを使うのでなんか違いがあるのだろうか。認証以外の情報がtokenとしてどんどん増えていくことを想定してのtokenなのかな。何かの記事でAPIだとセッションが使えないみたいなことが書いてあったんだけれども、なんで使えないのかもよくわからない。)
ユーザー登録をして、IDとパスワードを入力を含めたサイトであれば、
- 自分のサイトでログイン画面でIDとパスワードを入力
- IDとパスワードで該当のユーザーが登録されていたら、ユーザーの情報をもとにtokenを生成しクライアントに渡す
- 以降、サーバー側にAPIを投げる際にはtokenを付加して投げる
- サーバー側はtokenをデコードして、ユーザーが存在するかとか、不正なtokenじゃないかとかをチェックする
みたいな感じなんだと思う、
これが、GitHubとかTwitterとかの外部認証を用いた場合がいまいちよくわからない。
なんとなくこんな感じだと思う。
- 外部のサイト(GitHub)にリダイレクト
- 外部のサイト(GitHub)で ログイン画面でIDとパスワードを入力
- 外部のサイトから、自分のサイトにtoken付きでリダイレクト
- 自分のサイトでtokenを受け取り、ログイン用のAPIにtokenを渡してAPIを叩く。
- ログイン用のAPIで外部サイト(Githubとか)のユーザー情報を取得するようなAPIを叩く。
- 取得したユーザー情報を自分のサイトのDBに登録して、さらにユーザー情報をもとにしたtokenを生成する
- 以降は、自サイトのときと同じ。
ただ、いろいろ調べると、アクセストークンは、認証(誰か)ではなく認可(〜をしてよい)しかわからないので、そのまま認証に使うのはよくないよ的な記事がたくさんある。
OAuth2をそのまま認証に使ってはいけない理由 〜 雑なまとめ · GitHub
誰が、がわかるのは前述のアクセストークンを発行する使用のOAuthではなくOpenIDConnectなんだよ、とかもあるんだけれども、Githubを利用した認証と、OpneIDConnectの関係もよくわからない。GithubからIDトークンってもらえるのかしら。
[前編] IDトークンが分かれば OpenID Connect が分かる
また、OpenIDConnectなのかOAuthの話なのかわからないけれども、自サイトから外部サイトにリダイレクトするときにstateっていうパラメータを発行しておいて、外部サイトから自サイトに戻るときにstateに変更がないかを調べていると思う。
tech-lab.sios.jp
上記のサイトで、stateの意味をわかりやすく書いてくれているんだけれども、APIでセッションを使わない場合、どう実装するのかが謎。
Laravelの外部認証のライブラリを眺めてたんだけれども、セッションを使う場合と使わない場合で(stateless)で処理がわかれていて、使わない場合は、stateのチェックをしていないように見える。
github.com
ちゃんと確認できてないのであれなんだけれども、仮にしてないとしたら、それでいいのだろうか。
いろいろ整理したいんだけれども、なかなか時間と気持ちがなく更新をさぼっていたのでしょうもないので、最後にしょうもない記事を書くことにした。
JWTのtokenのデコードでエラー
とあるAPIを叩く際の認証にJWTを使うことにした。
環境はPHPで、以下のライブラリを使っていた。
github.com
四苦八苦してtokenを発行することに成功し、今度はそれをデコードして検証する機能を実装して、curlで検証していた。
curlでヘッダにtokenをつけて検証
$ curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxM…lOIn0.d0NPptNDHzoFFG2gL8WffARAOxnnnjDk-7qMsKc19nM" http://localhost:8000/api/1/users
しかし、コピペし忘れてたんだけれども、こんなエラーがでてしまった。
エラーメッセージ
Could not decode token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxM…lOIn0.d0NPptNDHzoFFG2gL8WffARAOxnnnjDk-7qMsKc19nM" is an invalid JWS
あれーと、JWTの中身をいろいろと見ていて、1時間ほど経過した際に気づきました。
あれ、エラーメッセージのtokenの内容、途中で省略されてんじゃねえか!と。
というのも、Chormeのコンソールにtokenを出力して、確認してたんですが、長い文字列は省略されていたみたいです。
ちゃんと、JSONオブジェクトを展開したものを使いましょうというしょうもない話でした。