【開発者向け】EC-CUBE API プラグイン勉強会 | EC-CUBE 名古屋 vol.36
API の提供側の話です♡
EC-CUBEの情報を扱いリスク
・個人情報満載
・決済に関わる情報を持ってる
・セキュリティ対策で重過失とされた事例もある
– – – OAuth2.0は認可フレームワークの仕様。- – —
Twitterはこれ。だけどきちんと準拠していない
FBは認可できなく認証になってるくらいオレオレになってる。
YahooとLINEのIDはわりとちゃんと準拠しつつも、拡張して認証させている。
– – –
Yahoo!Japan は OpenID Connectを利用してる
OAuth2.0の拡張版。
認証を取り扱うのが仕事。ソーシャルログインによる使われている。
アプリケーション間の認証を安全に行うための仕様
→相互妥当性検証が可能
OpenID Authorization 2.0とは別物
– – – まとめ – – –
・第三者のアプリケーションにユーザーID&パスワードを渡さずに
・誰を認証するか - 認証(Authentication)
・誰が誰になんの権限を与えるか - 認可(Authorization)
誰が誰になにを許可する
Authorization Code flow(Webアプり向け)と
認証とアクセストークンのエンドポイントが別れてて、2つサーバーを使う仕様
Implicit flow(ネイティブアプリ向け)
認証のエンドポイントだけで
アクセストークンはブラウザのアドレスに付与される
Refresh Tokenが無いのも特徴。セキュリティレベルが下がるから
OAuth2.0も包括
その他Google Identity Platform などをRest API記述するために Swagger仕様(今後のデファクトスタンダード)を採用してる
SwaggerUIを使うと簡単に使える
参照URL : https://ec-cube.github.io/api
EC-CUBE APIでは、
Customer(フロント側)とMember(管理画面側)に認証を提供している
APIクライアントは、各ユーザーと1対1の関係
MemberごとにAPIクライアントを作る
Customerマイページの隠しページ/mypage/api でapiクライアントを作れる
未サポート
・opened connect coreのうちoptional扱いのもの
・promptパラメータ/displayパラメータ(まるまるを許可しますか?という表示の仕方。デフォはpageとかだと全画面)
・hybrid flow (認証の仕様を両方使う)
・public client(会員情報がない人(認証されていない人)が利用できる仕様)
・dynamic registration/discoveryなどopened connectの関連仕様(public clientを使うための仕様)
##チュートリアルがあるよ
http://ec-cube.github.io/api_authorization.html
1. eccubeをローカルにインストール
2. 管理画面のプラグインから、プラグインをインストール
3. 管理画面側のapiクライアントを作る。認証することが前提なので、メンバー管理から作る
4. 設定→システム管理→メンバー管理→ログインしている管理者IDからapiクライアントを新規登録してapiクライアントのアプリケーション名を入れる。
5. redirect_url … 認証したあとの戻り先URL
6. クライアントidとクライアントシークレットをメモっておく。これをつかってアクセストークンをします。
7. authorization codeを登録します。1度ログアウトして…ここからの手順はチュートリアル(http://ec-cube.github.io/api_authorization.html)で。
「JSON デバック https://jwt.io/」
改ざんされていないかというチェックができる
id_tokenを使って秘密鍵をJWTで調べれますよ〜。
暗号化アルゴリズムを間違えないでっRS256ですよっ
EC-CUBE独自に実装しているもの
tokeninfo
/OAuth2/v0/tokeninfo?id_token=
{
"iss":"https:\/\/example.com",
"sub":"4nwsnbszIH4XuQnXwigtP8HaKQpjeGx499s0A9I1qko",
"aud":"2e8153023d6afb2fb29931dbf9a275ed4715f384",
"iat":1460535523,
"exp":1460539123,
"auth_time":1460535523,
"nonce":"random_nonce"
}
* iss – ID トークンの発行元。
* sub – ユーザー識別子。 id_token の公開鍵から生成される。
* aud – ID トークンの想定されるオーディエンス。 OAuth2.0 Client ID が使用される。
* iat – ID トークン発行時刻の UNIX タイムスタンプ。
* exp – ID トークン有効期限の UNIX タイムスタンプ。
* auth_time – 認証の発生時刻の UNIX タイムスタンプ。
* nonce – クライアントセッションの識別子。リプレイスアタック防止のために使用する。
この情報を元に、以下のような内容を検証する必要があります。参考
* iss の値が API の認証をしたホスト名と一致することを確認します。
* sub の値が id_token の公開鍵の thumbprint と一致することを確認します。JOSE_JWK::thumbprint() などで検証できます。
* aud の値が Client ID と一致することを確認します。
* iat の値が、現在のUNIXタイムスタンプ値 – 600秒 以上であることを確認します。
* exp の値が、現在時刻のUNIXタイムスタンプ値より大きいことを確認します。
* nonce の値が、クライアントで保持している nonce の値と同一であることを確認します。リプレイスアタック防止のため、セッションで保持している nonce を破棄します。
Member/Customer と OAuth2.0 Client の関係
* ログイン中の Member/Customer と OAuth2.0 Client の ID が相違している場合は、認可リクエスト時に access_denied エラーとなります。
redirect_uri の指定
Authorization Code Flow にて、 redirect_uri に urn:ietf:wg:oauth:2.0:oob を指定することで、 ブラウザの画面に Authorization code を表示されます。 curl を使用したテスト用途や、ネイティブアプリケーションなどに利用可能です。
実装してみましょう
・CSRF防止のためのstateパラメータは必須
・OAuth2.0では推奨になっているため、サポートしていないクライアント/SDKが多いので注意
・各言語のサンプル有り
・Java, FS, Python, PHP C言語
・Googleのさーびす OAuth 2.9 Playground(https://developers.google.com/oauthplayground/) endpoints: をカスタムにすると、Googleのサーバーを使って、accuseのapiが動くのをチェックできる
◯ accubeのAPIテストできるやつがあるので、を管理画面から使ってみましょ!
追加仕様
・Google Identity Providerを参考に追加実装したもの
・tokeninfoエンドポイント
・id_tokenを渡すと詳細情報をJSONに渡す
・urn:item:wg:oath:2,0:oob
・ネイティブアプリでAuthorization codeフローをしようとした場合、テスト用途で利用しようとするとき、管理画面に表示してくれる機能が実装されています。
## 実装について2
・customer/MemberごとにUserInfoとid_tokenのPublic keyが生成されます。
・UserInfo::subはPublic keyの指紋(thumbprint)です
・シングルサインオンをしたい場合は、もうちょっと改良した方がいい。
一応、実装してみました→https://github.com/EC-CUBE/eccube-api/issues/39#issuecomment-249665124
・id_tokenの検証は https://jet.io/ が便利
◯ 認証+全テーブルのCRUDを提供
CRUD APIについて
・RestfulなAPI
・Create=POST, Read=GET, Update=PUT, Delete=DELETE
・MemberのAPIクライアント編集画面から簡単に試せます
・一番後悔させている商品などは認証不要
・削除はdel_flgのあるテーブルのみ
・JSON<->EntityのMapperを独自に開発
・複合キーのテーブルはURLがか変わるので注意
・https://
・DoctrineのMetadataを横撮ってJSONとEntityをマッピングしている
## Jsonのフォーマット
コレクションの場合
プロパティの場合
配列の場合 オブジェクトに配列のセット