Force.com canvas入門ガイド

1,170 views
1,116 views

Published on

2013年10月25日に実施されたForce.com Canvas入門Webinarのプレゼン資料です。
https://events.developerforce.com/ja/events/webinars/jp-canvas

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,170
On SlideShare
0
From Embeds
0
Number of Embeds
124
Actions
Shares
0
Downloads
18
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Force.com canvas入門ガイド

  1. 1. Force.com Canvas入門ガイド 中嶋 一樹 テクニカルエバンジェリスト @nkjm Friday, October 25, 13
  2. 2. ハッシュタグでつぶやこう:#forcedotcomjp Agenda • Force.com Canvasとは? • 単純なiFrameとの違い • 接続アプリケーションの作成 • 組織における接続アプリケーションのアクセス設定 • Signed Request(署名付き要求)を使った認証方法 • シングルサインオン • Force.comへのAPIコール • VisualforceへのCanvasの埋め込み • フレームのリサイズ • Canvasアプリのパッケージング • 参考情報 Friday, October 25, 13
  3. 3. ハッシュタグでつぶやこう:#forcedotcomjp Force.com Canvasとは? Force.com SDKによる動的リサイズ • 外部アプリ iFrame 外部サーバーで提供されるWebアプリをForce.comの画面に組み込み、統合されたアプリとし て提供するためのフレームワーク • 画面を組み込むためにiFrameを利用。ただしフレームサイズを動的に変更するためのSDKを提 供しているため自然な画面表示が可能。 • 外部サーバーはForce.comのAPIを利用してデータベースにアクセスする。SDKがこのAPIアク セスをサポートする。 • APIの利用に必要となる認証に"Signed Request"という手法を用いてよりシンプルでセキュ アな認証を可能にしている Friday, October 25, 13 *OAuth 2.0も選択可能
  4. 4. ハッシュタグでつぶやこう:#forcedotcomjp 単純なiFrameとの違い • 外部アプリにはセッションIDではなく認証トークンが含まれたSigned Requestを送信できる。Signed Requestは秘密 • によって署名されているため途中の経路での改ざんや偽装を防止することができる。 認証トークンはOAuth2.0 Webフローでも取得できるが、複数回のリダイレクトが必要。Signed Request を利用すればリダイレクトが不要になる。 • セッションIDは常にログインユーザーのフルアクセス権限が与えられてしまうが、Signed Requestに含ま れる認証トークンでは必要な範囲に権限を限定することができる。 • Canvasアプリはどのユーザーがアクセスできるか、組織の管理者が設定可能。 Friday, October 25, 13
  5. 5. ハッシュタグでつぶやこう:#forcedotcomjp 単純なiFrameとの違い • 外部アプリにはセッションIDではなく認証トークンが含まれたSigned Requestを送信できる。Signed Requestは秘密 • によって署名されているため途中の経路での改ざんや偽装を防止することができる。 認証トークンはOAuth2.0 Webフローでも取得できるが、複数回のリダイレクトが必要。Signed Request を利用すればリダイレクトが不要になる。 ①iFrameのコンテンツ要求 ②認証サーバへのリダイレクト ③認証後アクセスコードと共に リダイレクト Force.com 外部アプリ ⑤トークン送信 ④トークンの要求 ⑥APIコール OAuth2.0 Webフロー • セッションIDは常にログインユーザーのフルアクセス権限が与えられてしまうが、Signed Requestに含ま れる認証トークンでは必要な範囲に権限を限定することができる。 • Canvasアプリはどのユーザーがアクセスできるか、組織の管理者が設定可能。 Friday, October 25, 13
  6. 6. ハッシュタグでつぶやこう:#forcedotcomjp 単純なiFrameとの違い • 外部アプリにはセッションIDではなく認証トークンが含まれたSigned Requestを送信できる。Signed Requestは秘密 • によって署名されているため途中の経路での改ざんや偽装を防止することができる。 認証トークンはOAuth2.0 Webフローでも取得できるが、複数回のリダイレクトが必要。Signed Request を利用すればリダイレクトが不要になる。 ①iFrameのコンテンツ要求と同時に ①iFrameのコンテンツ要求 ②認証サーバへのリダイレクト Signed Request送信 アクセストークン ③認証後アクセスコードと共に リダイレクト Force.com 外部アプリ ⑤トークン送信 Force.com 外部アプリ ②APIコール ④トークンの要求 ⑥APIコール OAuth2.0 Webフロー • Signed Requestのフロー セッションIDは常にログインユーザーのフルアクセス権限が与えられてしまうが、Signed Requestに含ま れる認証トークンでは必要な範囲に権限を限定することができる。 • Canvasアプリはどのユーザーがアクセスできるか、組織の管理者が設定可能。 Friday, October 25, 13
  7. 7. ハッシュタグでつぶやこう:#forcedotcomjp 接続アプリケーションの作成 • Canvasアプリはこの接続アプリケーションを作成した組織、またはインストールした組織で利用可能になる。 • 接続アプリケーションは開発者がこのアプリの名前、秘密 、権限範囲、外部アプリのURLや認証方式を定義す るためのもの。 • 作成手順 • ビルド > 作成 > アプリケーションで、「接続アプリケーション」のセクションで「新規」ボタンをクリック • 基本情報セクションを適当に入力 • OAuth設定セクションで「OAuth設定の有効化」にチェック => 認証方式にSigned Requestを利用する場合はOAuthの認 証フローは利用しませんが、このチェックにより生成されるConsumer Secretは依然として必要になるためチェックしま す。 • コールバックURLを「sfdc://success」と設定 => ダミーです。Signed Request方式では実際には利用されません。 • 選択したOAuth範囲を必要に応じて追加 • サポートされているアプリケーション種別セクションでForce.com Canvasにチェック • キャンバスアプリケーションのURLに外部アプリのトップURLを入力 => URLはhttpsが必要です。 • アクセス方法を署名付き要求(POST)に設定 => 後述のSigned Request方式を指定しています。 • 場所をCanvasアプリを表示させる場所に応じて設定 Friday, October 25, 13
  8. 8. ハッシュタグでつぶやこう:#forcedotcomjp 組織における接続アプリケーションのアクセス設定 • 組織内のどのユーザーがこのCanvasアプリにアクセスできるのかを設定する。 • 設定手順 • 管理 > アプリケーションを管理する > 接続アプリケーションで作成した接続アプリを選択 • OAuthポリシーセクションの許可されているユーザーを「管理者が承認したユーザーは事前承認済み」に設定して保存 • 関連リストのプロファイルまたは権限セットで、Canvasアプリにアクセスを許可す るプロファイル/または権限セットを追加する * この設定はあくまでこの組織内で有効な設定であり、パッケージには含めることはできません。 Friday, October 25, 13
  9. 9. ハッシュタグでつぶやこう:#forcedotcomjp Signed Request(署名付き要求)を使った認証方法 • 外部アプリはForce.comにAPIアクセスするための認証情報(トークン)が必要だが、この認証情報を含め ユーザーに関する情報をForce.comから外部アプリに初回の1リクエストで伝送する効率的な仕組み • Force.comから外部アプリには下記のフォーマットのデータ(Signed Request)を伴ったPOSTリクエス トが送信される。 dfj984ropjdjflsdf.09wjefokjljlsdfpjdogodjfgpsdjgdsgjlkdsjgf(以後省略) Canvas Request ハッシュ アプリの情報、ユーザーの情報、トークンなどがJSON形式で デリミター(ドット) 格納されておりそれをBase64エンコードした値 Canvas RequestをConsumer SecretをキーとしてHMAC SHA-256でハッ シュ化、さらにBase64エンコードした値 Force.com 外部アプリ ②Signed Requestを伴ったPOSTリクエスト ①ユーザーがCanvasアプリにアクセス Friday, October 25, 13
  10. 10. ハッシュタグでつぶやこう:#forcedotcomjp Signed Requestを使った認証方法(続き) • 外部アプリはこのリクエストを受け取り、 Consumer Secretを用いてこのリクエストが想 定されるForce.comアプリからのものであること、改ざんがないことを検証する。 • Canvas RequestをConsumer SecretをキーとしてHMAC SHA-256でハッシュ化し、Base64エン コードをおこなう • 上記値を受信したハッシュと比較し、等しければ検証は成功。 <?php // Signed Requestを.で分割 $sr_r = explode('.', $_POST["signed_request"], 2); // Canvas RequestをConsumer SecretをキーにしてHMAC SHA-256でハッシュ化。さらにBase64エンコード。 $calculated_value = base64_encode(hash_hmac("sha256", $sr_r[1], YOUR_CONSUMER_SECRET, true)); // 算出した値と、POSTリクエストに含まれていたハッシュ値を比較して検証 if ($sr_r[0] == $calculated_value){ return true; // 合格 } else { return false; // 不合格 } ?> Friday, October 25, 13 *サーバー側のサンプルコードはPHPを利用しています。
  11. 11. ハッシュタグでつぶやこう:#forcedotcomjp Signed Requestを使った認証方法(続き) • 外部アプリはCanvas RequestをBase64デコードし、APIコールに必要なトークン、インス タンスURLをはじめ必要な情報を取得することができる。 <?php // Signed Requestを.で分割 $sr_r = explode('.', $_POST["signed_request"], 2); // Canvas RequestをBase64デコードし、canvas_requestオブジェクトとして取得 $canvas_request = json_decode(base64_decode($sr_r[1])); // Javascriptから利用するためにJSON形式のままの変数を用意 $canvas_request_in_json = base64_decode($sr_r[1]); // APIアクセスに必要なアクセストークン、インスタンスURLは下記のように取得 $oauthToken = $canvas_request->client->oauthToken; $instanceUrl = $canvas_request->client->instanceUrl; ?> Friday, October 25, 13
  12. 12. ハッシュタグでつぶやこう:#forcedotcomjp Signed Requestを使った認証方法(続き) • Signed Requestが送信されるのはChatterタブのCanvas Appをクリックしたとき、およ びCanvasアプリが含まれるVisualforceページを表示させたときのみです。Canvasアプリ 内のリンクをクリックしたときには送信されません。後続のリクエストに備えて外部アプリは Canvas Requestを何らかの形でセッションに保存しておく必要があります。 • Safari等一部のブラウザはiFrame内からのCookieを拒絶するため、Canvas Requestの保 持にCookieが利用できないケースがあります。サーバー側で全リンクにセッションIDを自動 挿入する機能や、HTMLコンテンツ内にセッションIDを埋め込むなどのワークアラウンドを検 討してください。(例えばPHPではsession.use_trans_sidを有効にすることでCookieを 用いずにセッションの保持が可能) Cookie iFrame Friday, October 25, 13
  13. 13. ハッシュタグでつぶやこう:#forcedotcomjp シングルサインオン • 外部アプリ側でもデータベース等のリソースを保持しそのアクセスに認証が必要な場 合、シングルサインオン(SSO)をおこなうことがのぞましい。 Signed Requestに含まれるトークンでアクセス可能 Force.com Friday, October 25, 13 別途認証し、セッションを確立する必要がある 外部アプリ
  14. 14. ハッシュタグでつぶやこう:#forcedotcomjp シングルサインオン(続き) • Signed Requestを活用すればシンプルなSSOが可能。*またはSAMLを用いたSSOも構築可能 • あらかじめ外部アプリ側のアカウント情報にSalesforceユーザー名をマッピングしておく。*外部アプリ のユーザー名とSalesforceユーザー名が一致している場合には必要ありません。 追加 username password salesforce_username nakajima@mydom.com 90dfoj4BnM knakajima@sf.mydom.com yamashita@mydom.com kd8FIKJef8e tyamashita@sf.mydom.com 外部アプリのアカウント情報 • 外部アプリ側で通常どおりSigned Requestを検証する。 • Canvas Requestから抽出したSalesforceユーザー名を外部アプリ側のアカウント情報から検索。 ヒットすればそのユーザーですでに認証されていると見なしてセッションを発行する。 Friday, October 25, 13
  15. 15. ハッシュタグでつぶやこう:#forcedotcomjp シングルサインオン(続き) • Sample Code <?php // Signed Requestを.で分割 $sr_r = explode('.', $_POST["signed_request"], 2); // Canvas RequestをConsumer SecretをキーにしてHMAC SHA-256でハッシュ化。さらにBase64エンコード。 $calculated_value = base64_encode(hash_hmac("sha256", $sr_r[1], YOUR_CONSUMER_SECRET, true)); $canvas_request = json_decode(base64_decode($sr_r[1])); // 算出した値と、POSTリクエストに含まれていたハッシュ値を比較して検証 if ($sr_r[0] == $calculated_value){ // ローカルデータベース(PostgreSQL)から該当するユーザーを検索 $dbconn = pg_connect(YOUR_CONNECTION_STRING); $query = "select * from users where salesforce_username = '" . $canvas_request->context->user->userName . "'"; $result = pg_query($query); $result_all = pg_fetch_all($result); if (isset($result_all[0]["username"])){ // SSO成功 session_start(); $_SESSION["username"] = $result_all[0]["username"]; $_SESSION["canvas_request"] = $canvas_request; return true; } else { // Signed Requestの検証は成功しているが、SSOは失敗 return false; } } else { return false; // 不合格 } ?> Friday, October 25, 13
  16. 16. ハッシュタグでつぶやこう:#forcedotcomjp Force.comへのAPIコール • Force.comへはクライアント側(Javascript)、サーバ側、双方からAPIコール可能。 • クライアント側についてはクロスドメインアクセスとなるが、SDKを利用することでアクセス可 能となる。 サーバー側からのAPIコール Force.com 外部アプリ Canvas Requestから取得し たアクセストークン クライアント側(Javascript)からのAPIコール(SDKがサポート) *Javascriptは外部アプリからロードしたものなのでForce.comにアクセスす るとクロスドメインアクセス(通常ブラウザによりブロックされる)になるが、 サーバーから間接的に受け 取ったアクセストークン Friday, October 25, 13 SDKに含まれるProxy機能がこれを可能にしている。
  17. 17. ハッシュタグでつぶやこう:#forcedotcomjp Force.comへのAPIコール(続き) • Force.com Canvas SDKをインポート <script src="<?php echo $sr->canvas_request->client->instanceUrl;?>/canvas/sdk/js/<?php echo $sr->canvas_request->context->environment->version->api; ?>/canvas-all.js"></script> • APIコール(取引先データ取得) <script type="text/javascript"> var canvas_request = JSON.parse('<?php echo $canvas_request_in_json; ?>'); var url = '/services/data/v' + canvas_request.context.environment.version.api + '/query? q=SELECT+ID,NAME+FROM+ACCOUNT'; Sfdc.canvas.client.ajax( url, { client: canvas_request.client, method: 'GET', contentType: 'application/json', success: function(data){ if (data.status === 200){ console.log(data.payload.records); } else { console.log(data.statusText); } } } ); </script> Friday, October 25, 13
  18. 18. ハッシュタグでつぶやこう:#forcedotcomjp Force.comへのAPIコール(続き) • APIコール(取引先データ作成) <script type="text/javascript"> var canvas_request = JSON.parse('<?php echo $canvas_request_in_json; ?>'); var body = {Name: "Test Account"}; var url = '/services/data/v' + canvas_request.context.environment.version.api + '/sobjects/ Account'; Sfdc.canvas.client.ajax( url, { client: canvas_request.client, method: 'POST', contentType: 'application/json', data: JSON.stringify(body), success: function(data){ if (data.status === 201){ console.log('SUCCESS'); } else { console.log(data.statusText); } } } ); </script> Friday, October 25, 13
  19. 19. ハッシュタグでつぶやこう:#forcedotcomjp Force.comへのAPIコール(続き) • APIコール(取引先データ更新) <script type="text/javascript"> var canvas_request = JSON.parse('<?php echo $canvas_request_in_json; ?>'); var body = {Name: "Test Account"}; var record_id = ''; // 更新する取引先のレコードIDをセット var url = '/services/data/v' + canvas_request.context.environment.version.api + '/sobjects/ Account/' + record_id; Sfdc.canvas.client.ajax( url, { client: canvas_request.client, method: 'PATCH', contentType: 'application/json', data: JSON.stringify(body), success: function(data){ if (data.status === 204){ console.log('SUCCESS'); } else { console.log(data.statusText); } } } ); </script> Friday, October 25, 13
  20. 20. ハッシュタグでつぶやこう:#forcedotcomjp Force.comへのAPIコール(続き) • APIコール(取引先データ削除) <script type="text/javascript"> var canvas_request = JSON.parse('<?php echo $canvas_request_in_json; ?>'); var body = {Name: "Test Account"}; var record_id = ''; // 更新する取引先のレコードIDをセット var url = '/services/data/v' + canvas_request.context.environment.version.api + '/sobjects/ Account/' + record_id; Sfdc.canvas.client.ajax( url, { client: canvas_request.client, method: 'DELETE', contentType: 'application/json', data: JSON.stringify(body), success: function(data){ if (data.status === 204){ console.log('SUCCESS'); } else { console.log(data.statusText); } } } ); </script> Friday, October 25, 13
  21. 21. ハッシュタグでつぶやこう:#forcedotcomjp Visualforceへの埋め込み • Canvasアプリの表示場所はChatterタブ、またはVisualforceページ • VisualforceページではCanvas用のタグを用いて全体あるいは一部にCanvasアプ リを配置可能 // デフォルトでheightは900px、widthは800pxになります <apex:canvasApp namespacePrefix="myprefix" applicaitonName="My App" developerName="myapp" /> // parametersで任意の値をCanvas Requestに含めることができます。 <apex:canvasApp namespacePrefix="myprefix" applicaitonName="My App" developerName="myapp" parameters="{p1:'value1',p2:'value2'}" /> * VisualforceはAPIバージョン27.0以上が必要です。 * パッケージとして配布する場合、必ずnamespacePrefix属性とdeveloperName属性を指定してください。 * applicationName属性も同時に指定した方が表示が若干速くなります。 * parameters属性で指定した値はcanvas_request->context->environment->parametersで取得できま す。 * apex:canvasAppの完全な属性リストはVisualforce開発者ガイドの標準コンポーネントを参照ください。 Friday, October 25, 13
  22. 22. ハッシュタグでつぶやこう:#forcedotcomjp フレームのリサイズ 自動リサイズ無効 自動リサイズ有効 height=400px width=750pxとしたCanvasアプリの出力結果 • iFrameはHTMLの仕様上サイズを静的に指定する必要があり、動的なコンテンツを表示させた 場合スクロールバーが多重に表示される、またはコンテンツが途中で切れるといった現象が発 生しユーザービリティを損なう。 • SDKのautogrow(), resize()メソッドを利用することで、コンテンツに応じてフレームサイ ズを動的に変更し、上記の問題を解消できる。 Friday, October 25, 13
  23. 23. ハッシュタグでつぶやこう:#forcedotcomjp フレームのリサイズ(続き) Sfdc.canvas(function(){ sr = JSON.parse('<?php echo $canvas_request_in_json; ?>'); // フレームを縦横ともにコンテンツに応じて自動でリサイズする。デフォルトでは300msごとにコンテンツサイズの検出 がおこなわれる。 Sfdc.canvas.client.autogrow(sr.client); // 検出間隔を100msにセットして自動リサイズ Sfdc.canvas.client.autogrow(sr.client, true, 100); // 検出と自動リサイズを無効にする Sfdc.canvas.client.autogrow(sr.client, false); }); * HTMLでフレームサイズをheight, widthで指定しても自動リサイズ機能はフレームサイズを動的に変更しますが、maxHeight, maxWidthで指定したフレームサイズを超えることはありません。 Friday, October 25, 13
  24. 24. ハッシュタグでつぶやこう:#forcedotcomjp Canvasアプリのパッケージング • 管理パッケージに接続アプリケーションを含めることでCanvasアプリが配布可能になる • ユーザー組織では接続アプリケーションのアクセス設定をおこなう必要がある • 接続アプリケーションの定義を変更した場合は、パッケージを転送アップグレードすることで 即座にユーザー環境に変更を反映可能 *アプリケーションパートナーのみ インストール 接続アプリケーション 管理パッケージ 開発組織 組織A 組織B (Developer Edition) ユーザー組織 Friday, October 25, 13 組織C
  25. 25. ハッシュタグでつぶやこう:#forcedotcomjp 参考情報 • Force.com Canvas SDK開発者ガイド • http://developerforcejp.s3.amazonaws.com/developer/docs/platform_connect/ canvas_framework.pdf • DeveloperforceのCanvasまとめサイト • http://wiki.developerforce.com/page/Force.com_Canvas • Force.com Canvas SDKのリファレンス • http://htmlpreview.github.io/?https://raw.github.com/forcedotcom/ SalesforceCanvasJavascriptSDK/master/docs/index.html • Force.com Canvas Toolkit for PHP(サーバー側でのSigned Requestの取 り扱いをまとめたツールキット。Herokuでも利用可能) • https://github.com/nkjm/Force.com-Canvas-Toolkit-for-PHP Friday, October 25, 13
  26. 26. Developer Forceのソーシャルメディアをフォロー @developerforcejp/ #forceotcomjp Developer Force Japan +Developer Force Japan Developer Force Japan Friday, October 25, 13
  27. 27. アンケートにご協力を! http://bit.ly/dfcjwebinar Friday, October 25, 13

×