OAuth Multiple Access Tokenってどうなんでしょうか

@mad_pさんがまとめてくださったエントリを読んで、今回のネタを決めました。
#idcon8レポート - mad-pの日記

 * サービス上ではリソースの機密性に合わせてセキュリティーも変えられるが、APIだと難しい
  * → OAuth Multiple Access Token
  * scope, tokenを空白で区切って並べる

#idcon8レポート - mad-pの日記

真武さん: Multiple Access Tokenについて: scopeひとつに対してひとつトークンが来るの? 誰がまとめるのかどうか
* Y!ではconsumer keyと結びついている
* 真: OAuth2だとtoken要求時にscopeを送るし、複数のscopeをグルーピングしないと使えないAPIもある。Facebookもリストで送る。twitterもコンシューマキーに結びついている

#idcon8レポート - mad-pの日記

ではいきましょう。

OAuth Multiple Access Tokenって何の話?

Yahoo! JAPANの中の人が考えているらしい、"異なるセキュリティ要件"を持つAuthZ時の(Access/Refresh)Token出しわけの提案」といった感じでしょうか。
この件はこの前のIIWで発表したとかしないとか。

例としてあげられていたのは、こんな感じでした。

  • ServerはClientに異なるセキュリティ要件を持つ"ソーシャルプロフィール","決済"のAuthZを行う
  • Serverは"profile payment"というScopeを持つAccess Token,Refresh Tokenを発行する
  • "ソーシャルプロフィール"は長期間アクセスできても良い
  • "決済"は長くても24時間ぐらいしか使わせたくない
  • Refresh Tokenの有効期限って?短いほうの24時間になる
  • お金使わないユーザーでも有効期限が短くなる?利便性低い

ということで、別々のTokenにするのはどう?という提案です。

Google,FacebookとかでOAuth使うときに複数のScopeを指定できますが、あの位置づけは
"異なるScopeのAuthZを同時に行い、Scopeをまとめた一つのTokenを発行する"となっています。
それに対して、Y!Jがやりたいことは"異なるScopeのAuthZを同時に行いつつ、有効期限の異なるTokenを発行させたい"ということ。Tokenをまとめるのではなく、最初のAuthZのタイミングをまとめたいという感じでしょうか。

また、大事な点は「全てのScopeに個別のTokenを発行するわけではない」ということ。
"セキュリティ要件によるScopeのグルーピング"なので、そこをうまく仕様としてきめなければいけないと思います。

提案仕様

とりあえずOAuth 2.0の仕様を大きく変えたくないので、しれっとTokenを複数返す方法を提案しています。

Web Server Flowで返されるJSONレスポンス例:

{
    "access_token":"SlAV32hkKG",
    "expires_in":3600,
    "refresh_token":"8xLOxBtZp8",
    "scope":"profile payment"
}

これが、こうなるイメージです。

{
    "access_token":"SlAV32hkKG 2ndATokenString",
    "expires_in":"3600 3600",
    "refresh_token":"8xLOxBtZp8 2ndRToken",
    "scope":"profile payment"
}

Access TokenとRefresh Token,expires_inが2つになっています。
1個目がprofile用、2個目がpayment用です。
あれ?expires_in同じじゃんと思われた方もいると思いますが、Refresh Tokenの有効期限はOAuth 2.0の仕様に含まれていないので、書いていません。

足りない点

上記のレスポンスだけでは、仕様として成り立たない感や実装しにくい点がまだ残っていると思います。
そこで、思いついた部分を追加で提案してみます。

Scopeの区切り方が不明なのではっきりさせる

@novからの指摘にもありましたが、例えばClientは3個のScopeを要求し、Server側が2個 + 1個にTokenをわけたいときにうまく表現できない気がします。
"Scope分割のルール"をServerがClientに提示する必要がありそうです。

例として、"profile graph payment"の3つのScopeが要求されたときのことを考えましょう。
なるべくパラメータを変えたくないということで、"scope_groups"というレスポンスを追加します。

{
    "access_token":"SlAV32hkKG 2ndATokenString",
    "expires_in":"3600 3600",
    "refresh_token":"8xLOxBtZp8 2ndRToken",
    "scope":"profile graph payment"
    "scope_groups":{
      {
        "scope":"profile graph"
      },
      {
        "scope":"payment",
      }
    }
}

これでわかるでしょうか?ちょっと苦しいですね。

Refresh Tokenの有効期限をつけるように提案すべき

現在のOAuth 2.0の仕様では、Refresh Tokenの有効期限が返されない仕様になっています。
なので上の例を見たとおり有効期限の異なるRefresh Tokenを返してもわかりづらく、仕様にしてもわかりづらいでしょう。。。
Refresh Tokenの有効期限も仕様に含めてくれって偉い人たちに言った方がいいですね。

どうしようもなくなったら、access_token,expires_in,refresh_token,scopeの組み合わせを思い切ってわけちゃってもいい?

{
    "access_tokens":{
      {
      "access_token":"SlAV32hkKG",
      "expires_in":3600",
      "refresh_token":"8xLOxBtZp8",
      "scope":"profile graph"
      },
      {
      "access_token":"2ndATokenString",
      "expires_in":3600,
      "refresh_token":"2ndRToken",
      "scope":"payment"
      },
    }
}


まぁ、それはわかりやすいですが、あまり仕様から外れたことするとこう言われてしまうでしょう。
「Y!JのOAuthはOAuthじゃない!またY!OAuth作りやがったな!」ってね。

その他、UXなど

あとは、ユーザーへの見せ方とかで決めとく方がいいルールがいくつかありそうです。

  • TokenがExpireしたときは、そのscope group単体でAuthZしなおせばいい
  • ユーザーもscope group単位でRevokeできる方がいい?

まとめ

まだ決め切れていないことが多い拡張提案ですが、そもそもOAuth 2.0の仕様がもたついているので、いろいろまだ間に合う部分があると思います。
しかし、こうやって仕様を提案するということは大事なことだと思うのでY!Jには頑張ってもらいたいですね。

ではまた!