コンテンツへ移動

sdk/android

Chrome Custom Tabs、PKCE S256 認可コードフロー、Keystore バックアップの EncryptedSharedPreferences トークンストレージを使用した Android 向け Kotlin SDK。

Markdown で表示

状態

パッケージステータス:実装済み・ローカル検証済み。JVM 単体テスト(24 ケースパス)は PKCE 生成、OAuth state、メモリ内ストレージをカバーします。EncryptedSharedPreferences(Keystore AES-256-GCM)、Chrome Custom Tabs、App Links の動作は実際の Android デバイスまたはエミュレーターが必要です。実際の IdP ラウンドトリップは手動検証待ちです。このページは実装済みの動作を記録したものであり、本番対応の主張ではありません。

動作要件

  • Android API 26+(Android 8.0)
  • Kotlin 1.9+ および AndroidX

インストール

アプリモジュールの build.gradle.kts に依存関係を追加します:

dependencies {
    implementation("dev.xid:xid-android:0.1.0-alpha")
}

// Local development: add to settings.gradle.kts
includeBuild("../sdk/android")

マニフェストセットアップ

インテントフィルターでコールバック Activity を登録します。カスタムスキームより App Links(autoVerify 付き HTTPS スキーム)が推奨されます:

<!-- AndroidManifest.xml -->
<activity android:name=".AuthCallbackActivity" android:exported="true">
    <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="https"
              android:host="yourapp.example.com"
              android:pathPrefix="/auth/callback" />
    </intent-filter>
</activity>

クイックスタート

import dev.xid.sdk.Xid
import dev.xid.sdk.model.XidConfig

// 1. Initialize in Application.onCreate
Xid.configure(
    context = this,
    config = XidConfig(
        issuer = "https://xid.dev",
        clientId = "your_client_id",
        redirectUri = "https://yourapp.example.com/auth/callback",
        scopes = listOf("openid", "profile", "email", "offline_access"),
    )
)

// 2. Sign in (opens Chrome Custom Tabs)
lifecycleScope.launch { Xid.signIn(requireContext()) }

// 3. Handle redirect in AuthCallbackActivity
val session = Xid.handleRedirect(intent.data.toString())

// 4. Get current session (auto-refreshes near expiry)
val session = Xid.getSession()

// 5. Get access token
val token = Xid.getAccessToken()

// 6. Sign out
Xid.signOut(context = this, openEndSession = true)

コア API

方式 署名
configure fun configure(context: Context, config: XidConfig)
signIn suspend fun signIn(context: Context, options: SignInOptions? = null)
handleRedirect suspend fun handleRedirect(url: String): XidSession
getSession suspend fun getSession(): XidSession?
getAccessToken suspend fun getAccessToken(options: GetAccessTokenOptions? = null): String
signOut suspend fun signOut(context: Context? = null, openEndSession: Boolean = false)
setTokenStorage fun setTokenStorage(adapter: TokenStorageAdapter)

エラー型

すべての SDK エラーは sealed クラス XidException のサブタイプです:

サブクラス トリガー
NotConfigured configure() が呼び出されていません
UserCancelled ユーザーが完了せずに Custom Tabs を閉じました
StateMismatch OAuth state 不一致 — CSRF の可能性があります
TokenExchangeFailed トークンエンドポイントがエラーを返しました
TokenRefreshFailed リフレッシュトークンの有効期限切れまたは取り消し
NoSession サインアウト中に呼び出されたセッションメソッド

セキュリティ

  • パブリッククライアント — クライアントシークレットは保存・送信されません。
  • PKCE S256 のみ。サーバーは plain チャレンジメソッドを拒否します。
  • Android Keystore(AES-256-GCM)を使用した EncryptedSharedPreferences が保存時のトークンストアを保護します。
  • リクエストごとに生成されるランダムな OAuth state。CSRF を防ぐためリダイレクト時に検証されます。

既知の制限事項

  • JWKS による ID token 検証は実装済みでローカル単体テスト済みです。L4 には Android 実機または emulator と IdP の検証が必要です。
  • ユーザーが認可を完了せずに Custom Tabs を閉じたことを検出するメカニズムがありません。
  • シングルアカウント専用 — ストレージレイヤーは固定キーを使用します。
ナビゲーション

入力して検索...

矢印キーで移動Enter キーで選択Escape キーで閉じる