Estado
El estado del paquete es Implementado y verificado localmente. La suite de pruebas unitarias de Swift para el paquete de iOS se ejecuta correctamente en macOS. El comportamiento en un simulador o dispositivo y un recorrido de ida y vuelta con un IdP real en una instancia de XID activa siguen pendientes de verificación manual. Esta página documenta el comportamiento implementado; no afirma que esté listo para producción.
Estado del registro: UNPUBLISHED. Instala este SDK únicamente desde el checkout del código fuente del repositorio; no uses un registro de paquetes externo.
Requisitos
- iOS 16+ / macOS 13+
- Swift 5.9+ y Xcode 15+
- Sin dependencias de terceros: solo usa frameworks del sistema Apple
Instalación
Añade el paquete mediante Swift Package Manager en Xcode (File -> Add Package Dependencies) o directamente en Package.swift:
// Package.swift
dependencies: [
.package(path: "../xid/sdk/ios"),
],
targets: [
.target(name: "YourApp", dependencies: [.product(name: "Xid", package: "ios")]),
]Inicio rápido
import Xid
// 1. Configure in @main App.init. offline_access is rejected until DPoP is implemented.
Xid.shared.configure(options: XidConfiguration(
issuer: URL(string: "https://xid.dev")!,
clientId: "your_client_id",
redirectUri: URL(string: "com.example.app://auth/callback")!,
scopes: ["openid", "profile", "email"]
))
// 2. Sign in (opens ASWebAuthenticationSession)
try await Xid.shared.signIn()
// 3. Handle redirect in SceneDelegate
let session = try await Xid.shared.handleRedirect(url: callbackUrl)
// 4. Read the current unexpired session. Expiry requires reauthorization.
if let session = try await Xid.shared.getSession() {
let token = try await Xid.shared.getAccessToken()
}
// 5. Clear local state and optionally call end_session.
try await Xid.shared.signOut(callEndSession: true)API principal
| Método | Descripción |
|---|---|
configure(options:) |
Inicializa con issuer, clientId, redirectUri, scopes. Llámalo antes que los demás. |
signIn(options:) async throws |
Abre ASWebAuthenticationSession con la URL de autorización PKCE S256. Devuelve cuando finaliza la sesión del navegador. |
handleRedirect(url:) async throws -> XidSession |
Valida el estado OAuth, intercambia el código de autorización en el endpoint de tokens, persiste los tokens en Keychain y devuelve una sesión. |
getSession() async throws -> XidSession? |
Devuelve la sesión iOS actual no caducada; se borra el estado del token caducado y el método devuelve nil. |
getAccessToken(forceRefresh:) async throws -> String |
Devuelve el token de acceso actual no caducado. El SDK rechaza offline_access hasta que se implemente DPoP; la caducidad exige volver a autorizar. |
signOut(callEndSession:) async throws |
Limpia los tokens del Keychain. Pasa true para llamar al endpoint end_session desde el navegador. |
setTokenStorage(_:) throws |
Reemplaza el KeychainTokenStorage predeterminado con una implementación personalizada de TokenStorageAdapter. |
Adaptador de almacenamiento
El almacenamiento predeterminado usa Keychain con kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: los tokens no se sincronizan con iCloud Keychain. Implementa el protocolo TokenStorageAdapter para usar una política de Keychain empresarial:
struct EnterpriseKeychain: TokenStorageAdapter {
func save(key: String, value: String) throws { /* ... */ }
func load(key: String) throws -> String? { /* ... */ }
func delete(key: String) throws { /* ... */ }
}
try Xid.shared.setTokenStorage(EnterpriseKeychain())Seguridad
- Cliente público: no se almacena ni transmite ningún secreto de cliente.
- Solo PKCE S256. El servidor rechaza el método plain de challenge.
- Estado OAuth aleatorio generado por solicitud; validado en la redirección para prevenir CSRF.
- El code_verifier PKCE se escribe en el Keychain solo durante el flujo de autorización y se elimina inmediatamente después del intercambio de código.
- ASWebAuthenticationSession iniciada con prefersEphemeralWebBrowserSession = true para evitar compartir cookies del navegador entre apps.
Limitaciones conocidas
- La verificación de tokens de ID ES256/RS256 respaldada por JWKS, la validación del nonce y el cierre de sesión mediante end_session están implementados y probados localmente. Aún se requiere un recorrido de ida y vuelta con un IdP real en un dispositivo o simulador iOS antes de ofrecer compatibilidad L4.
- El comportamiento de Keychain debe verificarse en una prueba de dispositivo o simulador de Xcode.