状態
パッケージステータス:実装済み・ローカル検証済み。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 を閉じたことを検出するメカニズムがありません。
- シングルアカウント専用 — ストレージレイヤーは固定キーを使用します。