メインコンテンツに移動

モバイルアプリ

このガイドでは、k-IDウィジェットをモバイルアプリケーションに統合するためのベストプラクティスについて説明します。Webでは、ウィジェットは通常iframeに埋め込まれますが、モバイルアプリではウィジェットURLを効果的に表示するために異なるアプローチが必要です。

概要

k-IDウィジェット(CDKとAgeKit+)は、年齢ゲート、VPC、データ通知、権限管理、年齢確認インターフェースを含む完全なコンプライアンスフローを含むAPI呼び出しから返されるURLです。これらのウィジェットをモバイルアプリケーションに統合する場合、表示するためのいくつかのオプションがあり、それぞれ異なる機能とトレードオフがあります。主な考慮事項は次のとおりです:

  • AgeKeysサポート: ユーザーが将来の確認のためにAgeKeys(FIDOベースのパスキー)を作成して使用できるかどうか
  • 結果の通信: ウィジェット結果がアプリにどのように配信されるか
  • ユーザーエクスペリエンス: 統合のレベルとネイティブ感

モバイル実装方法

Androidオプション

Androidは、ウィジェットURLを表示するための3つの主要な方法を提供します:

  • Custom Tabs推奨 - アプリのブランディングを維持するカスタマイズされたChromeブラウザタブでウィジェットURLを開きます。これにより、ユーザーをアプリのコンテキスト内に保ちながら、完全なブラウザ機能を提供します。Custom TabsはChromeとCookieと認証状態を共有し、シームレスなエクスペリエンスを可能にします。

  • WebView - AndroidのネイティブWebViewコンポーネントを使用して、アプリ内にWebコンテンツを直接埋め込みます。実装は簡単ですが、WebViewは最新のWeb標準へのサポートが限られており、特定のブラウザ機能にアクセスできません。

推奨されません

WebViewはAgeKeysに必要なWebAuthnをサポートしていません。WebViewを使用してウィジェットを埋め込む場合、ユーザーはAgeKeysを作成または使用できません。完全なAgeKeysサポートを備えた最適なユーザーエクスペリエンスを得るには、代わりにCustom Tabsを使用してください。

  • Trusted Web Activity (TWA) - 主にProgressive Web Apps向けに設計されたフルスクリーンモードでWebコンテンツを表示します。TWAは、アプリとk-IDドメイン間でデジタルアセットリンクを確立する必要があります。デジタルアセットリンクが検出されない場合、TWAは自動的にCustom Tabsにフォールバックします。
推奨されません

Trusted Web Activitiesはウィジェット統合ではサポートされていません。k-IDのドメインでデジタルアセットリンクを設定する必要がありますが、これは利用できません。この場合、TWAはCustom Tabsにフォールバックするため、より簡単な実装のためにCustom Tabsを直接使用することをお勧めします。

iOSオプション

iOSは、ウィジェットURLを表示するための3つの主要な方法を提供します:

  • ASWebAuthenticationSession推奨 - 安全な認証フロー専用に設計されたこの方法は、システム管理のブラウザビューでWebコンテンツを表示します。SafariとCookieを共有し、WebAuthnなどの最新のWeb機能へのアクセスを提供するため、確認フローに最適です。

  • SFSafariViewController - SafariとCookieと認証状態を共有するSafariライクなインターフェースでWebコンテンツを表示します。これにより、アプリのコンテキストを維持しながら、馴染みのあるブラウジングエクスペリエンスを提供します。

  • WKWebView - アプリ内にWebコンテンツを埋め込むAppleの最新のWebビューコンポーネントです。AndroidのWebViewと同様に、WKWebViewは特定のWeb標準に制限があり、すべてのブラウザ機能にアクセスできません。

推奨されません

WKWebViewはAgeKeysに必要なWebAuthnをサポートしていません。WKWebViewを使用してウィジェットを埋め込む場合、ユーザーはAgeKeysを作成または使用できません。完全なAgeKeysサポートを備えた最適なユーザーエクスペリエンスを得るには、代わりにASWebAuthenticationSessionを使用してください。

AgeKeysサポートの制限

AgeKeysは、FIDOおよびWebAuthn標準に基づく再利用可能な匿名の年齢証明資格情報です。ユーザーは一度年齢を確認し、個人情報を開示することなく、異なるサービス間でその確認を再利用できます。

AgeKeysの制限

AgeKeysにはWebAuthnサポートが必要ですが、これはAndroid WebViewまたはiOS WKWebViewでは利用できません。これらのコンポーネントを使用してウィジェットを埋め込む場合、ユーザーは確認中にAgeKeysをオプションとして表示されず、確認成功後にAgeKeysを作成できません。

ユーザーに対してAgeKeysを有効にするには、次のいずれかの方法を使用する必要があります:

ウィジェット結果の受信

モバイルアプリは、ユーザーがウィジェットフローを完了した後に結果を受信する必要があります。2つのアプローチがあり、それぞれ異なる可用性があります:

コールバックURL(ユニバーサル方法)

推奨アプローチ

すべての実装方法で推奨されるアプローチは、コールバックURLを使用することです。ウィジェットURLを生成するためにAPIを呼び出す際に、redirectUrlパラメータを含めます。ウィジェットフローが完了すると、ウィジェットは結果をクエリパラメータとして含めてこのURLにリダイレクトします。

コールバックURLの利点:

  • すべての実装方法で動作
  • DOMメッセージよりも信頼性が高い
  • モバイルアプリの標準的なディープリンクパターン
  • アプリがバックグラウンドに移動しても、結果は常に配信されます

コールバックURLの仕組み

  1. アプリにディープリンクハンドラーを登録します(例:myapp://vpc-completeまたはmyapp://verification-complete
  2. APIを呼び出す際に、ディープリンクをredirectUrlとして含めます
  3. ウィジェットは完了後にディープリンクにリダイレクトします
  4. アプリがディープリンクを処理し、結果を抽出します
備考

リダイレクトは、ウィジェットURLがブラウザまたはWebビューで直接開かれた場合にのみ発生し、iframeに埋め込まれた場合は発生しません。

コールバックURLパラメータ

ウィジェットがコールバックURLにリダイレクトする際、ウィジェットタイプに関連するクエリパラメータが含まれます。例えば:

  • Age GateウィジェットにはverificationIdresultが含まれる場合があります
  • セッション関連のウィジェットにはsessionIdとステータス情報が含まれる場合があります
  • 年齢確認ウィジェットにはverificationIdresultが含まれます

コールバックURLの例:

myapp://vpc-complete?sessionId=608616da-4fd2-4742-82bf-ec1d4ffd8187&result=PASS
myapp://verification-complete?verificationId=7854909b-9124-4bed-9282-24b44c4a3c97&result=PASS

コールバックURLの実装

ウィジェットAPIを呼び出す際に、リクエストにredirectUrlを含めます。URLは次のいずれかになります:

  • HTTPS URL: https://example.com/vpc-complete
  • カスタムディープリンク: myapp://vpc-complete

DOMメッセージ(WebView/WKWebViewのみ)

Android WebViewまたはiOS WKWebViewを使用する場合、ウィジェットから送信されるJavaScriptメッセージをリッスンできます。これにより、以下が可能になります:

  • ウィジェット結果をリアルタイムで受信
  • Webビューを閉じるタイミングを制御
  • ウィジェットイベントに基づいてアプリのUIを更新

CDKウィジェットは、ウィジェットタイプに応じて異なるDOMイベントを発行します:

DOMメッセージは、ネイティブコードでインターセプトできるpostMessageイベントとして送信されます。利用可能なイベントの詳細については、DOMイベントの概要を参照してください。

限定的な可用性

DOMメッセージはWebViewとWKWebViewでのみ機能します。Custom TabsTrusted Web ActivityASWebAuthenticationSession、またはSFSafariViewControllerでは利用できません。

サードパーティアプリ認証フロー

ConnectIDなどの一部の認証方法では、認証プロセスの一環としてユーザーをサードパーティのモバイルアプリにリダイレクトする必要があります。例えば、ConnectIDはユーザーの銀行アプリを開いて本人確認を完了します。

サードパーティアプリフローの仕組み

サードパーティアプリを使用する認証方法を使用する場合、フローは複数のアプリケーションを経由してからアプリに戻ります:

ステップごとの説明:

  1. アプリがサーバーに認証URLをリクエストします
  2. サーバーがAPIキーを使用してk-ID APIを呼び出し、アプリのredirectUrlを含めます
  3. k-IDが認証インターフェースを含むURLをサーバーに返します
  4. サーバーがアプリにURLを返します
  5. アプリがWebコンポーネント(ASWebAuthenticationSessionまたはCustom Tabs)でURLを開きます
  6. ユーザーがConnectIDなどの認証方法を選択すると、k-ID UIがサードパーティの認証アプリ(銀行アプリなど)にディープリンクします
  7. 認証が完了すると、サードパーティアプリはデバイスのネイティブブラウザでk-IDの結果ページにリダイレクトします
  8. k-IDが保存されたredirectUrlを取得し、認証結果とともにユーザーをアプリにリダイレクトします

サードパーティアプリフローの重要な考慮事項

Webコンポーネントの要件: これらの認証方法は、埋め込みWebViewではなく、システムブラウザコンテキスト(ASWebAuthenticationSession、Custom Tabs、またはSFSafariViewController)で開く必要があります。サードパーティアプリのリダイレクトフローが正しく機能するには、完全なブラウザコンテキストが必要です。

ネイティブブラウザへのハンドオフ: サードパーティアプリが認証を完了すると、元のWebコンポーネントに直接戻るのではなく、デバイスのネイティブブラウザでk-ID URLにリダイレクトされます。これは、モバイルデバイスでのアプリ間リダイレクトの動作によるプラットフォームの制限です。

コールバックURLは必須: 認証フローが複数のアプリとブラウザを経由するため、redirectUrlパラメータは完了後にユーザーをアプリに戻すために重要です。サードパーティアプリ方法を使用する可能性のある認証を開始する際は、常にredirectUrlを含めてください。

サードパーティアプリフローのテスト

以下の認証方法はサードパーティアプリのリダイレクトを使用します:

  • ConnectID: モバイルアプリケーションでのリダイレクトフローを検証するためのテストアプリが含まれています。

方法の比較

方法プラットフォームAgeKeysDOMメッセージコールバックURL最適な用途
WebViewAndroid推奨されません(AgeKeysサポートなし)
Custom TabsAndroidほとんどのユースケース(推奨)
Trusted Web ActivityAndroid推奨されません(デジタルアセットリンクが必要)
WKWebViewiOS推奨されません(AgeKeysサポートなし)
ASWebAuthenticationSessioniOSほとんどのユースケース(推奨)
SFSafariViewControlleriOSSafariライクなエクスペリエンス

推奨実装

Android: Custom Tabs

機能とユーザーエクスペリエンスの最適なバランスを得るために、コールバックURLと共にCustom Tabsを使用します。

Custom Tabsを選ぶ理由:

  • WebAuthnによる完全なAgeKeysサポート
  • すべての最新Web機能へのアクセス
  • アプリブランディングによるシームレスなユーザーエクスペリエンス
  • 信頼性の高いコールバックメカニズム
  • Chromeと認証状態を共有

実装手順:

  1. コールバックURLのディープリンクハンドラーを登録します
  2. APIリクエストにredirectUrlを含めます(エンドポイントがサポートしている場合)
  3. Custom Tabsを使用してウィジェットURLを開きます
  4. ウィジェット結果でディープリンクコールバックを処理します

iOS: ASWebAuthenticationSession

安全でネイティブ感のあるコンプライアンスフローのために、コールバックURLと共にASWebAuthenticationSessionを使用します。

ASWebAuthenticationSessionを選ぶ理由:

  • WebAuthnによる完全なAgeKeysサポート
  • すべての最新Web機能へのアクセス
  • システム管理のセキュリティUI
  • SafariとCookieを共有
  • 信頼性の高いコールバックメカニズム

実装手順:

  1. コールバックURLのURLスキームハンドラーを登録します
  2. APIリクエストにredirectUrlを含めます(エンドポイントがサポートしている場合)
  3. ASWebAuthenticationSessionを使用してウィジェットURLを表示します
  4. ウィジェット結果でURLスキームコールバックを処理します

完全な実装例

推奨アプローチを実装するためのステップバイステップの例と完全なコードサンプルを以下に示します:

ステップ1: ディープリンクハンドラーの登録

Info.plistにURLスキームを登録します:

<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>

ステップ2: サーバーからウィジェットURLを生成

重要

ウィジェットURLは、モバイルアプリから直接ではなく、サーバーから生成する必要があります。これにより、APIキーがクライアント側のコードに公開されるのを防ぎます。モバイルアプリは独自のサーバーAPIを呼び出し、サーバーがk-IDへのサーバー間呼び出しを行います。

アーキテクチャの概要

サーバー実装

サーバーがAPIキーを使用してk-ID APIを呼び出します:

POST https://game-api.k-id.com/api/v1/widget/generate-e2e-url
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY

{
"jurisdiction": "US-CA",
"options": {
"redirectUrl": "myapp://vpc-complete"
}
}

レスポンス:

{
"id": "7854909b-9124-4bed-9282-24b44c4a3c97",
"url": "https://family.k-id.com/widget?token=eyJhbGciOiJFUzM4NCIs..."
}

モバイルクライアント実装

モバイルアプリがサーバーを呼び出してウィジェットURLを取得します:

import Foundation

func fetchWidgetUrl(completion: @escaping (URL?) -> Void) {
// k-IDではなく、自分のサーバーエンドポイントを呼び出す
guard let url = URL(string: "https://your-server.com/api/generate-widget-url") else {
completion(nil)
return
}

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
// 独自の認証を追加(セッショントークンなど)
request.setValue("Bearer USER_SESSION_TOKEN", forHTTPHeaderField: "Authorization")

let requestBody: [String: Any] = [
"jurisdiction": "US-CA",
"options": [
"redirectUrl": "myapp://vpc-complete"
]
]

guard let httpBody = try? JSONSerialization.data(withJSONObject: requestBody) else {
completion(nil)
return
}
request.httpBody = httpBody

URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil,
let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode),
let data = data,
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
let widgetUrlString = json["widgetUrl"] as? String,
let widgetUrl = URL(string: widgetUrlString) else {
completion(nil)
return
}
completion(widgetUrl)
}.resume()
}

ステップ3: ウィジェットの表示

import AuthenticationServices

// セッションをプロパティとして保存して、解放を防ぐ
var authSession: ASWebAuthenticationSession?

func displayWidget(widgetUrl: URL) {
authSession = ASWebAuthenticationSession(
url: widgetUrl,
callbackURLScheme: "myapp"
) { callbackURL, error in
if let error = error {
// エラーを処理(ユーザーがキャンセルした場合など)
return
}
if let callbackURL = callbackURL {
handleWidgetCallback(callbackURL)
}
}
authSession?.presentationContextProvider = self
authSession?.start()
}

ステップ4: コールバックの処理

func handleWidgetCallback(_ callbackURL: URL) {
guard let components = URLComponents(url: callbackURL, resolvingAgainstBaseURL: false),
let queryItems = components.queryItems else {
return
}

let sessionId = queryItems.first(where: { $0.name == "sessionId" })?.value
let verificationId = queryItems.first(where: { $0.name == "verificationId" })?.value
let result = queryItems.first(where: { $0.name == "result" })?.value

// ウィジェット結果に基づいてUIを更新
if result == "PASS" {
// 成功したフローを処理
} else if result == "FAIL" {
// 失敗したフローを処理
}

// オプション:APIエンドポイントを使用してサーバー側で確認
if let sessionId = sessionId {
verifyResultServerSide(sessionId: sessionId)
} else if let verificationId = verificationId {
verifyResultServerSide(verificationId: verificationId)
}
}
ベストプラクティス

セキュリティとデータの整合性のために、クライアント側のデータのみに依存するのではなく、適切なAPIエンドポイントを使用してサーバー側でウィジェット結果を常に確認してください。CDKの場合は、/session/getエンドポイントを使用します。AgeKit+の場合は、/age-verification/get-statusエンドポイントを使用します。

ウィジェットタイプ

k-IDは、特定のコンプライアンスワークフロー向けに設計されたいくつかのウィジェットタイプを提供します:

CDKウィジェット

AgeKit+ウィジェット

  • Access age verification: 完全な年齢確認インターフェースで、完全な確認フローを処理します
  • Waterfall flow: 異なる確認方法を順番に試すマルチメソッド確認フロー
  • Single method flow: 特定の方法を使用した直接確認

各ウィジェットタイプとその特定のユースケースの詳細については、CDKとAgeKit+のドキュメントのガイドを参照してください。