Section 4/161 menit
4. Associated Domains dan RP ID: Konfigurasi yang Benar
4. Associated Domains dan RP ID: Konfigurasi yang Benar
Apple App Site Association File
File ini harus tersedia di server Anda dan menentukan app mana yang boleh menggunakan domain ini sebagai RP ID:
swift
// https://example.com/.well-known/apple-app-site-association
{
"webcredentials": {
"apps": [
"TEAMID1.com.example.app",
"TEAMID1.com.example.appbeta",
"TEAMID2.com.partner.app"
]
}
}
Persyaratan server untuk file ini:
- Harus tersedia via HTTPS (bukan HTTP)
- Content-Type:
application/json - Tidak boleh ada redirect ke subdomain lain
- Harus tersedia tanpa autentikasi
- CDN caching OK, tapi harus accessible dari Apple's CDN crawler
Xcode Entitlements
swift
<!-- MyApp.entitlements -->
<key>com.apple.developer.associated-domains</key>
<array>
<string>webcredentials:example.com</string>
<string>webcredentials:api.example.com</string>
<!-- Jika punya staging domain: -->
<string>webcredentials:staging.example.com?mode=developer</string>
</array>
RP ID Hierarchy
RP ID harus berupa domain atau subdomain yang ada AASA-nya. Aturan keamanan:
swift
Domain: example.com
RP ID valid: "example.com" ← root domain
RP ID valid: "app.example.com" ← subdomain (jika AASA ada di app.example.com)
RP ID TIDAK valid: "com" ← terlalu umum (eTLD)
RP ID TIDAK valid: "other.com" ← domain lain
Mengapa RP ID penting:
- Passkey hanya bisa digunakan di domain yang sesuai RP ID
- Credential tidak bisa digunakan di domain berbeda → anti-phishing
- iOS verifikasi RP ID ke domain yang di-request saat autentikasi
Multi-Domain Configuration
swift
// App yang punya multiple domain (contoh: example.com dan example.co.id)
// Buat satu registration per RP ID yang didukung
struct PasskeyConfiguration {
let primaryRPID = "example.com"
let additionalRPIDs = ["example.co.id", "app.example.com"]
// Saat registrasi: user pilih atau sistem tentukan domain utama
func registrationProvider(for domain: String) -> ASAuthorizationPlatformPublicKeyCredentialProvider {
ASAuthorizationPlatformPublicKeyCredentialProvider(relyingPartyIdentifier: domain)
}
}