埋め込み署名
<bf-signing> は、Bona Fide の署名ページをページ内のサンドボックス化された iframe にレンダリングし、ドキュメントに合わせてサイズを調整して、
署名者の操作を DOM イベントとして通知します。フレームワークに依存せず、軽量な React と Vue のラッパーも同梱されています。
-
delivery: "embedded"を指定してエンベロープを作成します。これにより、受信者にはメールが送信されません。 -
署名者がページを開いたときに、サーバーでセッションを発行します。その際、
allowedOriginsにサイトのオリジンを指定します。 埋め込みページは、そこに含まれていない親ページとは通信しません。// Your backend (never expose the API key to the browser)const res = await fetch(`https://api.bonafidesign.com/v1/envelopes/${envelopeId}/sessions`, {method: 'POST',headers: { Authorization: `Bearer ${process.env.BONA_FIDE_API_KEY}`, 'Content-Type': 'application/json' },body: JSON.stringify({ recipient: recipientId, mode: 'embedded', allowedOrigins: ['https://app.example.com'] }),});const { token } = await res.json(); // 'bfs_…', single-use, 10 minutes by default -
トークンを使って要素をレンダリングします。
<script type="module" src="https://js.bonafidesign.com/v1"></script><bf-signing session="bfs_…" theme="auto" min-height="480" max-height="90vh"></bf-signing><script>const el = document.querySelector('bf-signing');el.addEventListener('completed', (e) => {// e.detail = { type: 'completed', envelope: 'env_…' }window.location.href = '/onboarding/next';});el.addEventListener('session_expiring', () => refreshSession());el.addEventListener('error', (e) => console.error(e.detail.code, e.detail.message));</script>import { BonaFideSigning } from '@bona-fide/embed/react';export function SignContract({ token }: { token: string }) {return (<BonaFideSigningsession={token}theme="auto"minHeight={480}maxHeight="90vh"onCompleted={(e) => console.log('envelope completed', e.envelope)}onDeclined={(e) => console.log('declined', e.reason)}onSessionExpiring={() => refreshSession()}onError={(e) => console.error(e.code, e.message)}/>);}<script setup lang="ts">import { BonaFideSigning } from '@bona-fide/embed/vue';defineProps<{ token: string }>();const done = (e: { envelope: string }) => console.log('envelope completed', e.envelope);</script><template><BonaFideSigning :session="token" theme="auto" :min-height="480" max-height="90vh" @completed="done" /></template> -
サーバーで結果を確認します。 ブラウザのイベントは UI 向けのシグナルとして扱い、結果の判断には
envelope.completedWebhook(またはGET /v1/envelopes/{id})を使用してください。
| 属性(React / Vue の prop) | デフォルト | 説明 |
|---|---|---|
session |
bfs_… トークン。変更するとフレームが再読み込みされます |
|
base-url(baseUrl) |
https://sign.bonafidesign.com/s/ |
デプロイメントのホスト型署名ルート |
theme |
auto |
auto、light、dark のいずれか |
locale |
署名ページに渡されます | |
min-height、max-height(minHeight、maxHeight) |
480、90vh |
ピクセルまたは vh。フレームはこの 2 つの間でドキュメントに合わせて大きくなり、それを超えると内部でスクロールします |
timeout |
30000 |
ページの読み込みを待つミリ秒数。超えるとコード load_timeout の error が発生します |
frame-title |
Document signing |
iframe のアクセシブルなタイトル |
要素には reload() メソッドもあります。たとえば新しいセッションを発行した後に使用します。
イベントはバブリングし、シャドウルートを越えて伝播し、ペイロードを event.detail に格納します。bf-event はすべてのイベントで発生します。
| イベント | detail |
|---|---|
ready |
{ type: 'ready' }:署名ページが読み込まれました |
field_completed |
{ type, field }:フィールドが入力されました |
signed |
{ type, recipient }:この受信者が送信しました |
completed |
{ type, envelope }:エンベロープが完了しました |
declined |
{ type, reason? } |
session_expiring |
{ type, expiresAt }:早めに新しいセッションを発行してください |
error |
{ type, code, message }。load_timeout と invalid_base_url を含みます |
React の prop は onReady、onFieldCompleted、onSigned、onCompleted、onDeclined、onSessionExpiring、
onError、onEvent です。Vue はイベント名(@completed、@session_expiring など)と event を emit します。
セキュリティモデル
Section titled “セキュリティモデル”- トークンは iframe の URL フラグメント(
#session=…)で渡されるため、サーバーやRefererヘッダーに届くことはありません。 署名ページはトークンを読み取って URL と履歴から削除し、メモリ内のアクセストークンと交換します。Cookie は使用しません。 - iframe はサンドボックス化されており(
allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads)、referrerpolicy="strict-origin"が設定されています。 - ページがメッセージを受け付けるのは、メッセージが要素自身の iframe から送られ、かつ
base-urlのオリジンから送られ、 かつ 名前空間付きのbona-fide.embed/1メッセージとして解析できる場合だけです。それ以外はすべて無視されます。 - 署名ページは、正確なオリジン(
*は使用しません)に対してのみ、しかもそのオリジンがセッションのallowedOriginsに含まれている場合にのみメッセージを送信します。API も、許可されていないオリジンからの埋め込みセッションの呼び出しを拒否します。