nappsについてのメモ
一部界隈で最近よく名前を聞くnappsについて調べてみたので、自分の理解のためにまとめます。
nappsとは
nappsとはNative Applications WGのことでモバイルのネイティブアプリでのSSOをOpenID Connectで実現するprofileを策定しています。(native(n) applications(apps)でnappsなんですかね?)
nappsでは、例えばスマートフォンに複数のネイティブアプリがインストールされていて、かつそれらがOAuthによるリソースアクセスとOpenID Connectによる認証を行う場合、複数のネイティブアプリ全てで認証と認可の管理が必要になってユーザビリティ的に厳しいよねという問題を解決するとしています。各アプリで認証するとかなっているとユーザビリティ的にもセキュリティ的にもつらいですね。
で、どうやってこの問題を解決するかというと、あるアプリをToken Agent(TA)と呼ばれる他のアプリの代わりにtokenを取得する特別なclientとし、TAを経由して他のアプリはtokenを取得するとしています。このTAによってtokenのprovisioningとSSOを実現します。TAでのみ認証させるようにすることでフィッシング防止にもなるかなーと思います。
リポジトリを見た感じ、nappsでは今のところ仕様は2つあるみたいです。
- OpenID Connect Native Application Token Agent Core 1.0
- OpenID Connect Native Application Token Agent API Bindings 1.0
1つがcoreとなる仕様で、もう1つはTAと他のアプリの間でのやりとりに関する仕様のようです。
語彙
OpenID Connectの語彙に加えて、いくつか語彙が加わっています。
- Token Agent (TA)
- その他のアプリに変わってaccess tokenなどを取得するアプリのことで、Authorization Serverごとにユーザーはこのアプリでのみ認証をします
- Primary Token
- TAに発行されるaccess token, refresh token, id_tokenのこと
- Secondary Token
- その他のアプリに発行されるaccess tokenのこと
- AppInfo Endpoint
フロー
Native Application Token Agent Coreでは以下のようなフローが想定されています。
省略して書いてありますが1,2は普通のOpenID Connectのフローです。このステップではTA自身に発行されるPrimary Tokenを取得します。ただし、1,2のOpenID ConnectのフローはAuthorization Flowでなければならず、Authorization Endpointではresponse_typeにcodeを、scopeにopenidとnappsという文字列を含めるようにします。napps scopeはTAがSecondary Tokenの取得に使用できるtokenを要求していることを示しています。
3,4でTA以外のアプリのSecondary Tokenを取得しています。TAからのリクエストは以下のようになります。Secondary Tokenはrefresh tokenを使って取得します。scopeに指定する値は後で出てくるAppInfo Endpointで得られるアプリごとの文字列で、scopeの値でSecondary Tokenを発行するアプリが指定されます。
POST /as/token.oauth2 HTTP/1.1 Host: as.example.com Content-Type: application/x-www-form-urlencoded;charset=UTF-8 grant_type=refresh_token& refresh_token=qANLTbu17rk17lPszecHRi7rqJt46pG1qx0nTAqXWH& scope=urn:oauth:boxx
レスポンスとしてaccess tokenもしくはid_tokenを受け取ります。id_tokenを受け取った場合はさらにid_tokenとaccess tokenを交換することになるのですが、そのケースについてはTBDとなっていました。アプリがTAにSecondary Tokenを要求する部分についてはapi bindingsで規定されるとのことです。
5でTokenの受け渡しをします。ここについてもapi bindingsで規定されるようです。
6でアプリからResource ServerにSecondary Tokenを使ったAPIリクエストをしています。さらに、このリクエストを受けて、Resource Serverは7のaccess tokenの検証を行います。access tokenの検証を行います。検証の方法は規定されていませんが、tokenの検証をAuthorization Serverに依頼したり、tokenのsignatureをResource Server内で検証するなどが例に出ています。
AppInfo Endpoint
また、Native Application Token Agent CoreではAppInfo Endpointというエンドポイントが存在しています。このエンドポイントにリクエストすることで、TAを利用してaccess tokenを取得するアプリのメタデータを取得できます。AppInfo Endpointへのリクエストはaccess_tokenとschemeの2つのパラメータを指定して、GETもしくはPOSTでリクエストします。access_tokenにはTAが取得したaccess_tokenを、schemeには"napps"という文字列を指定します。GETだとこんな感じになります。
GET /appinfo?scheme=napps HTTP/1.1 Host: server.example.com Authorization: Bearer SlAV32hkKG
{ "schema": "http:openid.net/schema/napps/1.0", "branding": { "companyname": "ABS", "companyiconurl": "http://www.ABS.com/logo.gif" }, "apps": [ { "name": "Boxx", "type": "native", "scope": "urn:oauth:boxx", "default_scopes": ["read" , "admin" ], "icon_uri": "http://www.example.com/pic.png", "custom_uri": "app1://callback-uri/" }, { "name": "test1", "type": "web", "scope": "urn:oauth:test1", "default_scopes": ["urn:oauth:web-sso"], "icon_uri": "http://www.example.com/pic.png", "web_init_ep": "http://init-sso.example.com/start" ] }
レスポンスの中身は以下のような内容になっています。
- name
- アプリの名前
- type
- アプリのタイプ(nariveかwebとなります)
- scope
- Secondary Tokenを取得する際に指定するscopeの値
- default_scopes
- アプリから明示的な指定がない場合、Secondary Token取得時にscopeパラメータに加える値
- custom_uri
AppInfo Endpointで得られるメタデータは、ランチャーのようにしてユーザーにアプリの情報を表示するのに使用したり、Secondary Tokenを取得する際に使われます。
感想
いろいろ資料を見ているとエンプラ向けの仕様なのかな?と思いました。LINEやFacebook的な、母艦となるアプリケーションが存在する場合でも有効そうなフローだとは感じます。
JICS2014 Day2 レポート
先週の1/14、15にJICS2014というカンファレンスが開催されました。両日参加したかったのですが、2日目のみの参加になってしまいました。
そんなわけで、以下2日目に自分が聴講した講演のメモです。
ID基盤構築101 - 伊藤忠テクノソリューションズ 富士榮 尚寛さん
- 頑張らないシステム化についての話
- ID基盤が無いと...
- それぞれのWebアプリとかがID管理を行うことになる
- 認証機能/DBをそれぞれで用意するので、開発側もユーザー側もコスト増
- 組織が変わった時とか、すべてのDBで操作が必要になる
- ID基盤を導入すると...
- 統合認証、統合データベース、プロビジョニング
- 統合認証システムで開発効率向上
- 監査も簡単になる
- ID基盤が何かって難しいし説明しにくい
- ID基盤導入のモチベーションの例
- アプリケーションをグループ、グローバルで使いたい
- クラウド(Google Apps, salesforce, office365)使いたい、BYODしたい
- ついでにやりたいことが出てくる
- リソース管理だとかロール管理
- それID基盤でやることじゃない
- スモールスタート、プロトタイピングしよう
- クラウドの仕様は良く変わる
- プロトタイピングしたほうがいい
ビッグデータとアイデンティティ - 国立情報学研究所 佐藤 一郎さん
- ビッグデータとID(識別子)について
- モノのidの仕事をしてきた
- RFIDとか
- 今回はそういった話
- 専門はOSとかミドルウェアとか、低レイヤなところ
- 商品とID
- 標準化に先にコミットした国ほど多くの国コードが割り当てられている
- 商品バーコードが生まれた理由
- スーパーのレジ待ち解消
- 当初はスーパーごとに商品にバーコードを貼り付け
- スーパー間でバーコードを共通化
- 予め商品につけた
- 全米で共通化したのち世界共通化
- JANコードは商品と商品に関する情報(販売価格など)をつなぐリンク
- JANコードがない商品は流通しない(存在しないと同じ)
- JANコードがあっても、商品情報がなければ販売しない
- JANコードの製造者番号 = 商品について責任を取る先
- 書籍にはISBNのバーコードもついてる
- もう一つは書籍のJANコード
- 書籍は再販制度により定価販売なので、書籍JANコードに価格を含めている
- JANコードを使ってA/Bテストはできるか -> パッケージの見た目が変わったぐらいではJANコードは変えられない
- パッケージの外寸とかが変わった場合はJANコードの変更が可能
- IDは関心ごとによって付けられる
- 商品の印刷デザインはJANコードの関心事ではない
- 公的な番号を民間利用しようとすると不便がある場合がある
- コンピュータは現実世界を直接扱えないので、現実世界の対象にIDを付番してそのIDを扱う
- ビッグデータ分析と言う前に対象に適切にIDを振ることが第一歩
- 関心ごとに応じて対象にIDを付番するのが第一歩
- モノのID
- 自動車番号
- 製造番号
- 生産日次、ライン番号がわかれば十分
- 大根とかにも一個一個ICタグを振るという話もあった
- 必要性が殆ど無い
- 現実社会はID社会と言ってもいい
- IDを変えることで世の中も変えられる
プライバシーとアイデンティティ - OpenID Foundation 崎村 夏彦さん
- プライバシーって何?
- privacy = private + -cy
- 個人情報であっても公知であるものはプライバシーの範疇ではない
- right to be let alone
- 個人の不可侵の権利
- 自己に対する自己の主権、すなわち人間の自由の権利
- "損害賠償に依る救済を与えるルール(プライバシー侵害があれば事後的に金銭賠償で救済)"から"物件としての救済を与えるルール"へ
- 自分に属する情報は自分がどう使うか決めていい -> アイデンティティ連携
- identityとは
- ある実態に関連した属性の集合
- = パーソナルデータの部分集合
- ある実態に関連した属性の集合
- アイデンティティ連携 = 誰に、何のために、何を提供するかを同意する
- 騙して使う例
- お客に正直なことを行ったら同意してもらえない -> お客の利益にならないことをやろうとする
- 目的の限定なんて出来ない、後から同意の取得なんて出来ない -> 20世紀的発想
- バレたら炎上
- ISO/IEC 29100のプライバシー原則
- 明示的同意?
- 常に要求するのが正しいのか?
- パブロフの犬的に同意してしまうようになってしまうのでは
- 常に要求するのが正しいのか?
- そもそも同意の向きが逆
- 企業が同意する
- 個人によるプライバシー侵害
- 見なかったことにするプライバシー
- MACアドレスとか取れちゃうけど捨てる、とか
- リスペクト、せよ!
- 人間(ユーザー)をリスペクトすることが大切
パーソナルデータ利活用の最前線
Twitterのデータ提供と活用 - Twitter Japan 牧野 友衛さん
- メディアからの報道からユーザーによる発信へ
- モバイルからのアクセスが75%以上
- 元々SMSからの利用を想定していた
- 情報利用とプライバシー保護
- 国内だとNTT DataがTweet Dataの再販売をしている
- 利用例
楽天のデータサイエンスによるEC革命 - 楽天 北川 拓也さん
- 楽天とamazon
- 感情価値のほうが大事なのでは?!
- 感情価値の向上をあらゆる領域で
- 楽天はBtoBtoC
- 楽天(B) -> 店舗(B) -> ユーザー(C)
- サービス向上
- 買ったものに幸せを感じる人と買うことを幸せに感じる人がいる
- 感情価値が買い始める理由となる
- eコマースを盛り上げる
- IDがあれば欲しいものがわかる
ID連携の広がりとともに増すセキュリティの重要性 - 株式会社野村総合研究所
- ID統合ではなくID連携
- 企業間ID連携によって、異業種間のID連携をすることで価値を生み出す
- 価値が高まると攻撃対象となる可能性も高くなる
2020年のポイントサービス - パネルディスカッション
将来のポイントサービスはどう進化するのか
- 安岡さん
- 最終消費支出: 234.4兆円
- 登録の簡便さよりもインセンティブ(ポイント)やアフターサービスなどのメリットがあることを重視している
- ポイント導入のメリットは顧客囲い込み、優良顧客化、新規顧客獲得、相互総客
- 値引きではなくポイントなのは、ポイントのほうが誘引効果が高いから
- 前さん
- 北川さん
- ポイントの収集は日本人特有のものかもしれない
- 特別ポイントの親和性の高いビジネス = カード・決済ビジネス
- 価格競争になってしまってはいけない
- 値引きとしてのポイントシステムではいけない
- ライフスタイル・ライフステージに応じたサービス提供が必要
- 池谷さん
過去のポイントのそもそもの役割は?
- 90sに紙スタンプカードからポイントカードに変わったことによって顧客識別が可能に
- 楽天カードに加入したらポイント付与とかは、最近やりはじめたことなのでは
現在のポイントはどうか?
- 共通 or 独自
- 企業側は困ってる
- インセンティブ、価格競争が潜在化してる
- インセンティブとかやめても実際は変わらないのでは
- インセンティブにしか興味ないユーザーを育成してしまってる
- 企業側は困ってる
- 今は囲い込みではなく、識別できた結果を上手く使わないといけない段階
- 価格よりリテンション
- 獲得施策としてポイントを使う
- IDの普及によって決済手段として使えるようになってきた
- リアルとネットの融合ってまだまだだよね
- 会場だと、Tポイントカード持っている人が全体の半分、PontaもRも半分ぐらいいる
- だいたいみんな全部もってるのでは
- ビッグデータとポイント
- ポイントとの関係っていうのではなく、IDとの関係
- 将来的にはポイントがbitcoinのような通貨に統合されるかも
未来のポイントはどうか?
- ポイントシステムの引き合いの波はある
- ポイントカードの引き合いは、今は減少してる感じ
- このままでいいのかな、って企業は思っているのでは
- 今はクーポンの引き合いの方が多い
- スマホとポイントの融合をどうするか
- 走ったこと(ランニング)に対してクーポンもらえるみたいなベンチャーはUSにすでにある
- ポイントからの脱却をしないといけない(北川さん)
- ポイントは使い続けるけど、頼らないようにする
情報銀行とパーソナルデータシステム - パネルディスカッション
- モデレーター
- 崎村 夏彦さん
パネリスト
- 慶応義塾大学 砂原 秀樹さん
- 日本ヒューレット・パッカード(株) 佐藤 慶浩さん
崎村さん
- 個人からの同意を得ることは不可能と思い込んで無断で使っている現状
- 本人にアクセスすることは不可能と思っている
- この想定は古臭い
- この前提を切り替える
- 本人にアクセスすることは不可能と思っている
- OpenID
- IdPに属性を集約
- 古典的コンシューマIdPモデル
- ユーザーの同意を元に同意済みデータをサービスに渡す
- 後から拒否もできる
- 課題
- 広告モデルで成り立つIdPでは、ユーザーとIdPの間に利益相反がある
- パーソナルデータの利用目的がわかりにくいため有効な同意をユーザーができない
- OpenPDS(Personal Data System)
- 予めPDSに同意のルールを設定しておく
- de-personalizedしてpublicに出すことも出来る
- 予めPDSに同意のルールを設定しておく
- 個人からの同意を得ることは不可能と思い込んで無断で使っている現状
情報銀行とは(砂原さん)
- パーソナル情報を信託して預ける仕組み
- 銀行はメタファー
- パーソナルデータを資産として扱うのは筋が良くないかもというのはある
- bigdataの利活用
- 本当にやりたいのは統計データの活用ではなく、個人のために、個人の情報を使って活用する
- 情報漏洩や不正利用の問題を解決するために正しく利用するための基板が必要
- パーソナルデータは今は企業のものになってしまってる
- 個人が企業の許可なしに使えない状態
- パーソナルデータは企業と個人の共有物
- パーソナルデータが総合化される
- 総合化されたデータを信託する場所 -> 情報銀行
- 社会受容性が一番大事
mitkitのpdsとの違いは?
個人情報保護法改正について(佐藤さん)
- IT総合戦略本部パーソナルデータ検討会技術WGの論点
- 個人情報を第三者に提供するときは本人からの同意を得る必要がある
- 情報を預かった事業者から別の事業者にデータを渡すときも
- 今は匿名化するなどして渡している
- 安全な匿名化
- そんなものはない
- 匿名性の高低はあるけど、完全なものはない、ケースバイケースである
- 安全なレベルはあるのでは
- そんなものもない
- 安全なレベルはあるのでは
- 再識別の禁止をする
- 再識別の困難性
- これのレベルを定めた
- 再識別の困難性
- 識別を特定を分けて考える
- パーソナルデータの利活用は刃物の取り扱いのようなもの
- まとめ
- 匿名化、統計化に安全基準はない
- ビジネス要求がなければ議論できない
- 提供先の禁止義務の監視は難しい
- ターゲットマーケティングにおいても個人を特定する属性情報の入手は必須ではない
現在の法律では第3者提供ができないから緩和しないといけないけどゆるゆるだといけない
- 基本サービスを享受するために個人情報を利用することが当然のような場合は同意を求めないほうがいいのでは?という話がWGでもでた(佐藤さん)
- 極端な例なのでコンセンサスは取れなかった
- データが漏れてしまった時の責任を考えておく必要がある(砂原さん)
- まとめ
グローバルクラウド時代のアイデンティティとデータの所在
- モデレーター
- KDDI(株) 藤井 彰人さん
パネリスト
- さくらインターネット(株) 舘野 正明 さん
- アマゾンデータサービスジャパン(株) 玉川 憲さん
- 宮内宏法律事務所 宮内 宏さん
クラウドの利用が増えてきた
- マーケットが成長してる
- ここ5年でクラウドを取り巻く環境はどう変化したか
- クラウドが盛り上がってきた背景
- エンタープライズとコンシューマの境界線はどこか
- awsもコンシューマからエンタープライズに向かって普及していった
- amazonはawsの客で、amazonのサーバはすべてaws
- パブリッククラウドのほうが先端的なハードウェアが使えるケースも有る
- クラウドの安全性について(宮内さん)
- 例えばアメリカにサーバがあるとpatriot actに...(聞き取れず)
- 厳密にはそんなに心配ではないけれど
- EUから日本にデータ持ってくるのは大変かも
- EUデータ指令
- 国内で普通に使っていて心配なのはデータが漏れるとか無くなるとか
- ファーストサーバとか...
- "ちゃんとやっている加減"をどう伝えるのか
- 例えばアメリカにサーバがあるとpatriot actに...(聞き取れず)
- データはデフォルト暗号化にしていくトレンドがある
- どこのサーバを利用するか場所を指定できる(舘野さん)
- SaaSなら難しいけどIaaSならどの地域(国)に置かれているかわからないというリスクはない
- クラウド時代のアイデンティティ
- idの連携の役割の一つは認証の連携
- データの連携もついてくる
- 自分のデータがどう集約されるのか
- USには帝国データバンクの個人版のようなものがある
- こういうのが日本で出来たら怖い
- 安易なID連携は危険
- 想定していないID同士の紐付けは嫌ですよね
- 企業買収によって思わぬIDの紐付きが行われる可能性もある
- 国によってもかなり違う
- idの連携の役割の一つは認証の連携
総括 - 国立情報学研究所 中村 素典さん
- 今年のキーワード(崎村さん)
- Password is Dead
- personal data
- 個人情報保護法改正の大綱が6月に出るので、要望があれば言いましょう
- 次回は暖かい時期にやりたいですね
ac.jsを試してみました
結構前の話になりますが、OpenID TechNight Vol.9に参加した時にac.jsなるものがあると聞いたので、試してみました。
ac.jsとは
ac.jsとはaccount chooserを既存サイトに組み込むためのJavaScriptライブラリです。ac.jsを使用することで、account chooserのUXを既存のwebsiteに導入することができます。http://accountchooser.net から辿れるac.jsの解説ドキュメントにac.jsの簡単な導入方法があったり、少し細かい設定について書いてあるドキュメントもあるので、今回はそれらを参考に試しました。ちなみに、ac.jsはApache License 2.0です。
試す
今回は簡単なlegacy login(従来のemail, passwordなどを使ってログインする形式)を実装しました。
デフォルトでは以下のような構成のパスになります。パスはscriptタグ中に設定を記述することで変更することもできます。
名称 | パス | 用途 |
---|---|---|
homeUrl | / | アプリのhome screen |
loginUrl | /account-login | ログインページ |
userStatusUrl | /account-status | ステータス確認エンドポイント |
signupUrl | /account-create | アカウント作成ページ |
動作の流れ
以下のような動作になります。
- ユーザーがWeb Pageにアクセスし、ログイン画面に遷移します。
- accountchooser.com上にアカウントが存在していると、ac.jsによりaccountchooser.comにリダイレクトが行われます。
- ユーザーがアカウントを選択します。
- ログイン画面に戻ります。
- ログイン画面からuserStatusUrlにPOSTでリクエストが行われます。
- userStatusUrlでは、Email(及びproviderId)を見て登録済みのユーザーであれば {"registered":true} を返し、未登録のユーザーであれば {"registered":false} を返します。
- providerIdが指定されていたら {"registered":IP-Url} を返します。IP-UrlはIdPを利用してログインするためのURL。このパターンは今回は実装しません。
- ac.jsにより、{"registered":true} であればログイン画面に、{"registered":false} であればサインアップ画面にユーザーをリダイレクトさせます。
- loginUrlおよびsignupUrlでは従来通りのログイン・アカウント作成処理を行います。
- ログインが完了したら、ac.jsを含んだコンテンツを返します。
- ac.jsによりaccountchooser.comにリダイレクトが行われ、既にaccountchooser.comに存在しているアカウントであればhomeUrlにリダイレクトされ、存在していなければstoreするかどうかの確認がaccountchooser.comで行われます。確認後、homeUrlにリダイレクトされます。
実装
今回はデフォルトのパスで実装しました。それぞれのパスのhtml・JavaScriptは以下のようになります。 実際のサインアップ、ログイン処理は別途実装するか既存の実装を利用することになりますが、そのあたりは省略してます。 また、ac.jsは自動でinput fieldを埋めることもしてくれるのですが、対象となるinput fieldのidは各endpointのパスと同様に設定で変更可能です。
homeUrl
homeUrlのコンテンツはなんでも構いませんが、こんな感じで。ユーザーがログインしていなかったらloginUrlに飛ばす、もしくはloginUrlのリンクを貼ることになると思います。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>homeUrl</title>
</head>
<body>
<h1>homeUrl</h1>
<a href="/account-login">login</a>
</body>
</html>
loginUrl
ac.jsを読み込むことと、formを設置する必要があります。formにはid=emailとid=passwordのinput fieldを設置します。accountchooser.comにアカウントが存在していない場合、リダイレクトが発生しないので、アカウント作成画面へのリンクでも貼っておきます(そのまま従来のログインをしても構いません)。ログインが成功したらアカウントの情報をscriptタグ内に記述することで、アカウントの情報をaccountchooser.comにstoreする処理が行われます。accountchooser.comにstoreした後はhomeUrlにリダイレクトされます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>loginUrl</title>
<script type="text/javascript" src="https://www.accountchooser.com/ac.js">
storeAccount: {
email: "foo@example.com",
displayName: "bang_yy",
photoUrl: "https://si0.twimg.com/profile_images/1146622182/___.png"
}
</script>
</head>
<body>
<h1>loginUrl</h1>
<form action="account-check" method="POST">
<ul>
<li>email: <input id="email" type="text" name="email"></li>
<li>password: <input id="password" type="password" name="password"></li>
<li><input id="submit" type="submit" value="submit"></li>
</ul>
</form>
<a href="/account-create">create account</a>
</body>
</html>
userStatusUrl
このエンドポイントはaccountchooser.comからPOSTされてくるユーザーのアカウント情報を見て、すでにアカウントが自サイトに存在していれば{"registered":true}を、存在していなければ{"regisitered":false}を、IdPにリダイレクトする場合は、{"registered":"IP-uri"}としてIdPを利用してログインするためのURLを返します。今回はlegacy loginなので最後のパターンはありません。
signupUrl
accountchooser.com経由で遷移してきたパターンだと、id=displayName, photoUrl, emailのinput fieldに自動でfillしてくれます。アカウント作成が成功したらアカウントの情報をscriptタグ内に記述します。このアカウントの情報をaccountchooser.comにstoreします。accountchooser.comにstore後はhomeUrlにリダイレクトされます。 また、loginUrlでaccountchooser.comにアカウントが存在していない場合はaccountchooser.comにリダイレクトがされないので、従来通りアカウント作成用の画面を表示する必要があります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>signupUrl</title>
<script type="text/javascript" src="https://www.accountchooser.com/ac.js">
storeAccount: {
email: "foo@example.com",
displayName: "bang_yy",
photoUrl: "https://si0.twimg.com/profile_images/1146622182/___.png"
}
</script>
</head>
<body>
<h1>signupUrl</h1>
<form method="POST">
<ul>
<li>displayName: <input id="displayName" type="text" name="displayName"></li>
<li>photoUrl: <input id="photoUrl" type="text" name="photoUrl"></li>
<li>email: <input id="email" type="text" name="email"></li>
<li>password: <input id="password" type="password" name="password"></li>
<li>confirm password: <input id="confirm" type="password" value="" name="confirm"></li>
<li><input id="submit" type="submit" valur="submit"></li>
</ul>
</form>
</body>
</html>
Identity Provider Filtering
今回は指定していませんが、Facebook loginなどを実装している場合は、以下のように記述することでサポートしているIdPのアカウントをaccountchooser.com上で表示させることができます。
<script>
accountchooser.CONFIG.providers = ["yahoo.com", "facebook.com" ];
</script>
まとめ
今回のように、ac.jsを単純に組み込むだけだとそんなに良いUXにはなりませんが、ac.jsは他にもいろいろとできるのでもっとUXの良いフローの実装もできます。 あと、ac.jsでlegacy loginだけできてもあまり嬉しくないのでidPを使ったログインを実装したいところですが、ac.jsを使う場合のfederated loginではOAuthなりOpenID Connectなりの実装はRPがすることになります。
ac.jsはまだまだ変更がありそうな気がするので(実際、書いてる間にIdentity Provider Filteringの仕様が変わってました)、時折見ていこうかなと思います。
OAuth2.0対応サービスのstate, redirect_uriパラメータの扱い色々
この前行われたidconで、OAuth2対応サービスのstateパラメータとredirect_uriパラメータの扱いってどうなってる?という話題があったのと、以前途中まで調べたものがあったので、いい機会なのでまとめてみました。
stateパラメータとredirect_uriパラメータについて
まずstateパラメータとredirect_uriパラメータについてです。が、ちょうどstateパラメータとredirect_uriパラメータについて書かれたエントリがありましたので、そちらをどうぞ!
利用する側としては、もしstateパラメータが利用できなければredirect_uriにquery parameterでnonceなどを渡してstateパラメータの代わりにしたいところです。
調べたこと
今回はstateパラメータとredirect_uriパラメータの扱いについて、下記の5つのサービスを調べました。
- mixi
- foursquare
Facebookはstateパラメータが使用可能です。 redirect_uriに指定するURLは、下記の範囲内であればquery parameterを付加したりパスを変えたりできます。
https://developers.facebook.com/docs/authentication/server-side/
For security, the redirect_uri must have the same base domain as that specified in the App Domain property of your app's settings, or be a URL of the form https://apps.facebook.com/YOUR_APP_NAMESPACE.
mixi
mixiもstateパラメータをサポートしています。 mixiではredirect_uriは事前に登録する必要があり、また、authorization request時にredirect_uriを指定せず、登録したURLにリダイレクトするという仕様なので、リクエストごとに異なるquery parameterをつけるようなことはできません。
Googleもstateパラメータは使用できることがちゃんとドキュメントに書いてあります。
https://developers.google.com/accounts/docs/OAuth2WebServer
Indicates the Google API access your application is requesting. The values passed in this parameter inform the consent page shown to the user. There is an inverse relationship between the number of permissions requested and the likelihood of obtaining user consent.
redirect_urlはauthorization request時に指定できますが、redirect_uriはclient idに対して登録されたものの内どれか1つにマッチするものでないといけません。
stateパラメータ使えます。
http://instagram.com/developer/authentication/
Note: You may provide an optional state parameter to carry through any server-specific state you need to, for example, protect against CSRF issues.
redirect_uriは、query parameterが許されるパターンが明記されています。詳細に書いてあるというわけではないんですが、簡潔な説明で結構わかりやすいです。
foursquare
OAuth関連のドキュメントには書いていなかったのですが、試したところstateパラメータが使えました。 また、redirect_uriパラメータについては、これもドキュメントに書かれているわけではないですが、登録したredirect_uriにquery parameter加えてを指定することができました。(登録したredirect_uriの下位パスの指定を無視しているようです。前方一致?) 一応、チュートリアルにはstateパラメータを使ったサンプルがあったので、ドキュメントには使えるパラメータを明記しておいてほしいなーと思います。
まとめ
stateパラメータとredirect_uriパラメータの扱いは結構気になる部分だったのですが、個人的には意外とstateパラメータがサポートされているなーという感じでした。ありがたいですね。また、redirect_uriの扱いはサービスごとにかなり違うようです。
あ、stateパラメータが使える場合はちゃんとstateパラメータ使いましょう。redirect_uriでどうにかするのはあくまで次善の策だと思います。
参考
- Facebook: http://developers.facebook.com/docs/authentication/
- mixi: http://developer.mixi.co.jp/connect/mixi_graph_api/api_auth/
- Google: http://code.google.com/intl/ja/apis/accounts/docs/OAuth2.html
- Instagram: http://instagram.com/developer/authentication/
- foursquare : https://developer.foursquare.com/docs/oauth.html
Facebookの認証ダイアログの仕様変更をまとめてみた
皆さんFacebook使ってますか?私はどちらかというとTwitterを使ってます。
下記のポストで説明されているのですが、Facebookが認証ダイアログの仕様を変えるようです。この変更が中々興味深い感じだったのでまとめてみます。
https://developers.facebook.com/blog/post/633/
変更点
今回の主な変更点は4つです。
1. ユーザーによるアプリのactivityの公開範囲設定
Facebookではウォールのポストごとに公開範囲を設定できますが、同じようにアプリがウォールにactivityを投稿する際の公開範囲を認証ダイアログで設定できるようになります。開発者がdeveloper appのDefault Activity Privacyでデフォルトの公開範囲を設定できるようにもなります。
2. アプリの説明エリアの追加
そのままなのですが、認証ダイアログにアプリの説明を行うためのエリアが追加されます。ユーザーにとっても開発者にとっても、アプリの説明が行えることはありがたいことですね。
3. Optionalなpermissionの表示
Extended permissionsを認証ダイアログの2つ目の画面で表示するようになります。この画面では、ユーザーに対して要求されているOptionalなpermissionを提示し、ユーザーはこれらのpermissionを拒否することもできるようになります。
また、developer appのExplanation for Permissionsの項目にpermissionを要求している理由を記入することができます。
あと、offline_access permissionがdeprecadeになります。あの、有効期限が設定されないaccess tokenのやつです。その代わりにaccess tokenを交換してexpireをresetすることが可能になるようです。
4. シームレスな認可手順の採用
この機能を有効にするとFacebook上でアプリのインストールを行う際にinlineでダイアログを表示することができるようです。
ユーザーによるpermissionの拒否について
3つめの変更が面白いですね。Facebookが定義しているpermissionはUser & Friend Permissionsと呼ばれるpermissionとExtended Permissionsと呼ばれるpermissionに大きく分類される(page用のpermissionもあったりはします)のですが、今回の認証ダイアログ変更でユーザーが拒否を行うことができるようになるpermissionはExtended Permissionsのみです。
実際に試すと以下のような感じになります。
まず、authZ endpointにリクエストします。今回はscopeにはuser_about_me(User & Friend Permissions)とread_friendlists(Extended Permissions)を指定してみます。
https://www.facebook.com/dialog/oauth?client_id=
&redirect_uri= &scope=user_about_me,read_friendlists&response_type=code
認証ダイアログはこんな感じになっています
インストールすると2つめの画面が表示されるので、
右上の×ボタンでpermissionの拒否ができます。
このあとGraph APIを使ってユーザーが許可しているpermissionを確認すると、
https://graph.facebook.com/
/permissions?access_token=
{ "data": [ { "installed": 1, "user_about_me": 1 } ] }
のように、ちゃんと拒否できていることがわかります。
開発者はaccess tokenを取得した時点ではユーザーが許可したpermissionを把握することができないので、Graph APIを使うなどしてユーザーに許可されたpermissionを確認する必要があります。ユーザーに許可されていないpermissionが必要な機能を選択された時点で"この機能を試すにはpermission: aを許可する必要があります"などと表示してauthZ endpointへのリンクを提示するようにするのがいいのでしょうか。
まとめ
ユーザーのコントロールできる範囲が広がり、良い方向で仕様変更が行われたように感じました。ついでと言っちゃ何ですが、この調子でaccess tokenとかをJSONで返すようにしてくれないですかね...
GeolocationAPI使ってみた
位置情報面白いですよね!
そんなわけで、GeolocationAPIを使ってみたのでまとめます。あまり難しいことを考えずに使う分にはすごい簡単でした。
GeolocationAPIとはなんぞや
まずGeolocationAPIて何ってことですが、specによると"各デバイスの実装により取得できる緯度経度のような位置情報を提供するインターフェースである"とありました。簡単に言ってしまうとjavascriptで"35.0000,135.0000"みたいな緯度経度の形式で現在地の情報を取得できるAPIのことです。
使ってみる
GeolocationAPIには
- getCurrentPosition(現在地を取得する)
- watchPosition(現在地を定期的に取得する)
- clearWatch(現在地を定期的に取得するのをやめる。watchPositionに対応しています)
の3つのAPIがあります。今回はgetCurrentPositionのみの使用だったので、getCurrentPositionについてまとめます。調べただけですが、他の2つのAPIもかなり簡単に使えるようでした。
getCurrentPositionは以下のような仕様になっています。
void getCurrentPosition(successCallback[, errorCallback[, options]]);
successCallbackには現在地を取得できたときのコールバックを、同様にerrorCallbackには現在地を取得できなかったときのコールバックを指定します。optionsにはAPI呼び出し時のoptionを指定します。optionsは下記のようなオブジェクトを渡して指定します。
var options = { timeout: 10000, maximumAge: 20000, enableHighAccuracy: true };
timeoutは現在地取得にかける時間(ミリ秒で指定)、maximumAgeはいつまでの位置情報のキャッシュを受け入れるかを指定します(ミリ秒で指定。0だとキャッシュの使用を許可しません)、enableHighAccuracyはアプリケーションに対して最も正確な位置情報を取得するように指定します(ただし、レスポンスが遅くなったりします)
あとは、GeolocationAPIを実装していないブラウザのために、
if (navigator.geolocation) { //GeolocationAPI使える! } else { //GeolocationAPI使えない! }
として機能テストしてあげます。
実際はこんな感じの実装になりました。
var options = { timeout: 10000, maximumAge: 20000, enableHighAccuracy: true }; if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( function(position){ var loc = position.coords.latitude + ',' + position.coords.longitude; alert(loc); }, function() { alert('位置情報の取得に失敗しました'); }, options); } else { alert('お使いのブラウザではこの機能はサポートされていません'); }
まとめ
かんたんですね!スマホ用のWebアプリで定期的に現在地を取得したりすると面白いことができそうです。