認証とApp Links
SDKはシステムブラウザーでOpenTesterのログインを開きます。ユーザーが接続を承認すると、コールバックのワンタイムコードをPKCEで検証し、アプリ単位のトークンと交換します。パスワードやGoogleログイントークンはホストアプリに渡しません。
Androidアプリ → ブラウザーログイン → 参加承認の確認
← 登録済みコールバック + code + state
Android SDK → コード交換 → アプリ単位トークン → 権限確認 / 報告送信1. コールバックを登録する
開発者コンソールに次のようなHTTPSコールバックを登録し、OpenTesterConfig.redirectUriにも同じ値を設定します。
https://your-app.example.com/opentester/callbackSDKはscheme、authority、path、stateを検証します。設定するURLにqueryやfragmentを含めることはできません。応答時にサーバーがcodeとstateをqueryとして追加します。
2. Android App Linksを設定する
debugビルドの例ではapp/src/debug/AndroidManifest.xmlに配置します。既存設定と統合し、パッケージ名とドメインを置き換えます。
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:name="com.example.app.TesterApplication">
<activity
android:name="com.example.app.TesterActivity"
android:exported="true"
android:launchMode="singleTask">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="your-app.example.com"
android:path="/opentester/callback" />
</intent-filter>
</activity>
</application>
</manifest>Androidのリンク宣言にはHTTPとHTTPSを含めますが、OpenTesterに登録するコールバックはHTTPSです。SDKは異なるschemeの応答を拒否します。Android App Links公式ガイドを参照してください。
コールバックのドメインで/.well-known/assetlinks.jsonを公開し、インストールされるアプリのapplication IDと署名証明書のSHA-256フィンガープリントを設定します。
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.app",
"sha256_cert_fingerprints": ["YOUR_SIGNING_CERTIFICATE_SHA256"]
}
}
]フィンガープリントは実際の値に置き換えます。Play App Signingではユーザーがインストールするアプリの証明書を使います。debugテストではテスト用ドメインにdebugのapplication IDと証明書を設定します。ウェブサイト関連付けガイドを参照してください。
3. ログインとコールバックを処理する
このActivityはクイックスタートのTesterApplicationを使います。app/src/debug/java/com/example/app/TesterActivity.ktに配置し、テスト画面から開きます。SDKの依存関係に含まれるKotlin Coroutinesを利用します。
package com.example.app
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import dev.opentester.sdk.OpenTesterException
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
class TesterActivity : Activity() {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
private val tester get() = (application as TesterApplication).tester
private lateinit var status: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
status = TextView(this)
val login = Button(this).apply {
text = "テスターログイン"
setOnClickListener { tester.authenticate(this@TesterActivity) }
}
setContentView(LinearLayout(this).apply {
orientation = LinearLayout.VERTICAL
addView(login)
addView(status)
})
consumeCallback(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
consumeCallback(intent)
}
private fun consumeCallback(incoming: Intent) {
val uri = incoming.data ?: return
incoming.data = null // Activity再生成時に同じコールバックを再処理しません。
scope.launch {
try {
val grant = tester.handleCallback(uri)
status.text = "${grant.user.name}さん、テストを開始できます。"
} catch (e: CancellationException) {
throw e
} catch (e: OpenTesterException) {
status.text = e.message
}
}
}
override fun onDestroy() {
scope.cancel()
super.onDestroy()
}
}独自のシステムブラウザー起動処理にはcreateAuthenticationUri()を使います。呼ぶたびに新しいログインが始まるため、URL確認のために繰り返し呼ばないでください。ログイン画面をWebViewに埋め込まないでください。
セッションの有効期間と再ログイン
| 項目 | 動作 |
|---|---|
| 認証待ち状態 | SDKメモリに最大15分保持 |
| サーバーのワンタイムコード | 2分間有効、交換は1回のみ |
| アプリ単位トークン | 1時間有効 |
| プロセス終了 | トークンとPKCE状態が失われるため再ログイン |
| 新しいログイン開始 | 既存SDKセッションを消去し、新しいPKCE状態を生成 |
logout() | メモリ内トークンと進行中の認証を削除 |
トークンの自動更新はありません。handleCallback()の通信エラーでもログインからやり直します。logout()はブラウザーCookieを消去せず、発行済みサーバートークンを即時失効させるものでもありません。
参加権限を確認する
テスト画面に入るとき、コルーチンから呼び出せます。
val grant = tester.checkAccess()サーバーの現在の承認状態を確認します。報告送信時も承認を確認し、取り消されていれば拒否します。AccessGrantを保存してオフラインの承認判定に使わないでください。
SDK認証が示すのはOpenTesterの参加権限です。アプリ自身のバックエンドには別途認証・認可を実装します。SDKはGoogle Playの参加状況や連続参加日数を判定しません。