Resumen
La mayoría de los usuarios abandona en el formulario de registro: un nombre de usuario, una contraseña que hay que recordar, un código por e-mail que acaba en el spam. Con KlugAuth tocan Continuar con Apple o Continuar con Google y listo.
KlugAuth muestra el inicio de sesión nativo de cada plataforma: la hoja de Apple con Face ID / Touch ID en iOS y macOS, la hoja de cuentas de Android (Credential Manager) para Google y la ventana de inicio de sesión del sistema para Google en iOS y macOS. Devuelve el token de identidad del proveedor junto con tu nonce, listo para verificarse en tu servidor, además del código de autorización de Apple que necesitas para revocar el vínculo cuando se elimina una cuenta (directriz 5.1.1(v) de la App Store).
No se incluye ningún SDK de Google: el inicio de sesión de Google en iOS y macOS usa el flujo OAuth estándar con PKCE en la hoja del navegador del sistema, por lo que la extensión sigue siendo pequeña.
KlugAuth funciona en la versión actual de nuestras apps, nuestra prueba de concepto, para el registro, el inicio de sesión y la confirmación del cierre de sesión de un dispositivo con Apple o Google.
Funciones
- Autónoma: una ANE, sin biblioteca central ni ANE de dependencias que añadir
- Sign in with Apple en iOS 13+, macOS 10.15+ y apps de iPad en Macs con Apple silicon
- Sign in with Google en Android (Credential Manager) y en iOS / macOS (ventana de inicio de sesión del sistema, sin SDK de Google)
- Token de identidad, ID de usuario, e-mail y nombre; código de autorización de Apple para renovación y revocación
- Utilidad de nonce para protección contra repetición (Apple lleva su SHA-256, Google el valor sin procesar)
- Comprobación del estado de credenciales de Apple (autorizado / revocado) para usuarios recurrentes
- Eventos separados de éxito, cancelación y error; la cancelación se notifica, nunca como error
Plataformas compatibles
Sign in with Apple en Android es posible con el flujo web de Apple y una pequeña página en el servidor; podemos proporcionarlo como parte de un proyecto. isSupported (Apple) e isGoogleSupported indican a tu código lo que ofrece el dispositivo.
Primeros pasos
Añade la extensión al descriptor de tu aplicación:
<extensions>
<extensionID>com.klug.auth.KlugAuth</extensionID>
</extensions>
Para Sign in with Apple, añade el entitlement (iOS: Entitlements en el descriptor; macOS: al firmar):
<key>com.apple.developer.applesignin</key> <array><string>Default</string></array>
Para Google, crea clientes OAuth en la consola de Google Cloud: un cliente web (su ID es la audiencia del token en Android), un cliente Android con el nombre de tu paquete y SHA-1, y un cliente iOS para iOS y macOS.
Ejemplos de código
Cinco flujos completos, desde los botones hasta tu servidor. Cada llamada devuelve de inmediato; los resultados llegan como KlugAuthEvents. Documentación completa →
import com.klug.auth.KlugAuth; import com.klug.auth.KlugAuthEvent; var auth:KlugAuth = KlugAuth.getInstance(); var nonce:String = ""; // a fresh one for every attempt appleButton.visible = auth.isSupported; // iOS 13+, macOS 10.15+, iPad apps on the Mac googleButton.visible = auth.isGoogleSupported; // Android, iOS 13+, macOS 10.15+ auth.addEventListener( KlugAuthEvent.APPLE_SUCCESS, onAppleSuccess ); auth.addEventListener( KlugAuthEvent.APPLE_CANCELED, onCanceled ); auth.addEventListener( KlugAuthEvent.APPLE_ERROR, onError ); auth.addEventListener( KlugAuthEvent.GOOGLE_SUCCESS, onGoogleSuccess ); auth.addEventListener( KlugAuthEvent.GOOGLE_CANCELED, onCanceled ); auth.addEventListener( KlugAuthEvent.GOOGLE_ERROR, onError );
function signInWithApple():void { nonce = KlugAuth.generateNonce(); // 32 random bytes as hex, used once if ( !auth.signInWithApple( nonce ) ) // false: not supported, or a sheet is already open showMessage( "Sign in with Apple is not available." ); // your app function } function onAppleSuccess( e:KlugAuthEvent ):void { // the token carries SHA-256 of the nonce: the server hashes the raw value and compares sendToServer( "apple", e.identityToken, nonce, e.fullName, e.authorizationCode ); saveAppleUserID( e.userID ); // stable for this Apple ID; your app function // e.email and the names arrive only on the FIRST authorization; // the e-mail is always inside the identity token } // your app function: the server verifies the token and signs the user in function sendToServer( provider:String, idToken:String, rawNonce:String, name:String, appleCode:String = "" ):void { var vars:URLVariables = new URLVariables(); vars.provider = provider; vars.id_token = idToken; vars.nonce = rawNonce; vars.name = name; if ( appleCode != "" ) vars.code = appleCode; // lets the server revoke the link later var req:URLRequest = new URLRequest( "https://your.server/auth" ); req.method = URLRequestMethod.POST; req.data = vars; var loader:URLLoader = new URLLoader(); loader.addEventListener( Event.COMPLETE, onServerAnswer ); // your app function loader.load( req ); }
import flash.system.Capabilities; // Android: the WEB client ID, which is the token audience on your server. // iOS and macOS: the iOS client ID, used in the system sign-in window. var googleClientId:String = Capabilities.manufacturer.indexOf( "Android" ) >= 0 ? "YOUR_WEB_CLIENT_ID.apps.googleusercontent.com" : "YOUR_IOS_CLIENT_ID.apps.googleusercontent.com"; function signInWithGoogle():void { nonce = KlugAuth.generateNonce(); // Google puts the raw value into the token if ( !auth.signInWithGoogle( googleClientId, nonce ) ) // false: no client ID, or already open showMessage( "Google sign-in could not start." ); } function onGoogleSuccess( e:KlugAuthEvent ):void { // e.userID is the account e-mail; names arrive every time sendToServer( "google", e.identityToken, nonce, e.fullName ); }
function onCanceled( e:KlugAuthEvent ):void { // the user closed the sheet: not an error, simply stay on the start screen } function onError( e:KlugAuthEvent ):void { if ( e.type == KlugAuthEvent.GOOGLE_ERROR && e.errorCode == "NO_ACCOUNT" ) showMessage( "Please add a Google account to this device first." ); // Android else showMessage( "Sign-in failed: " + e.errorMessage ); // e.errorCode for your log }
auth.addEventListener( KlugAuthEvent.APPLE_CREDENTIAL_STATE, function( e:KlugAuthEvent ):void { // e.state: authorized | revoked | notFound | transferred | unknown if ( e.state == "revoked" || e.state == "notFound" ) signOut(); // your app function: the user removed the app from their Apple ID }); var savedID:String = loadAppleUserID(); // stored after APPLE_SUCCESS; your app function if ( auth.isSupported && savedID != "" ) auth.getCredentialState( savedID ); // Apple only: iOS and macOS
Resumen de la API
| KlugAuth.getInstance() | Devuelve la instancia única. |
| isSupported | Verdadero donde Sign in with Apple está disponible (iOS, macOS). |
| isGoogleSupported | Verdadero donde Sign in with Google está disponible (Android, iOS, macOS). |
| generateNonce() | Estático. Un nonce aleatorio nuevo (32 bytes en hexadecimal); úsalo una sola vez y envía el mismo valor a tu servidor. |
| signInWithApple(nonce) | Abre la hoja de inicio de sesión de Apple. Devuelve false si no pudo iniciarse (no compatible, o ya hay un inicio de sesión en curso). |
| signInWithGoogle(clientId, nonce) | Abre el inicio de sesión de Google. Android: el ID de cliente web; iOS / macOS: el ID de cliente iOS. Devuelve false si no pudo iniciarse. |
| getCredentialState(userID) | Pregunta a Apple si el usuario sigue autorizado; la respuesta llega como APPLE_CREDENTIAL_STATE. iOS y macOS. |
| KlugAuthEvent | identityToken, authorizationCode, userID, email, givenName, familyName, fullName, state, errorCode, errorMessage. |
Eventos
| APPLE_SUCCESS | identityToken, authorizationCode, userID; email y los nombres solo en la primera autorización. |
| APPLE_CANCELED | El usuario cerró la hoja. |
| APPLE_ERROR | errorCode y errorMessage del sistema. |
| APPLE_CREDENTIAL_STATE | userID y state: authorized · revoked · notFound · transferred · unknown |
| GOOGLE_SUCCESS | identityToken, userID (el e-mail de la cuenta), email, givenName, familyName. |
| GOOGLE_CANCELED | El usuario cerró la hoja. |
| GOOGLE_ERROR | errorCode y errorMessage; en Android NO_ACCOUNT cuando el dispositivo no tiene cuenta de Google. |
Compra KlugAuth
Una licencia anual para una aplicación AIR, con todas las actualizaciones durante 12 meses. Tras el pago recibes la extensión, la biblioteca ActionScript y la documentación por e-mail, normalmente en un día hábil. Licencia y términos
- Licencia para una aplicación AIR
- Todas las actualizaciones durante 12 meses
- Sin soporte
- Licencia para una aplicación AIR
- Todas las actualizaciones durante 12 meses
- Respuesta por e-mail en un plazo de 7 días
- Licencia para una aplicación AIR
- Todas las actualizaciones durante 12 meses
- Respuesta por e-mail en un plazo de 48 horas
Requisitos
| AIR SDK | 51.x (HARMAN) |
| iOS | iOS 13 o posterior |
| Android | Android 6 o posterior, servicios de Google Play |
| macOS | macOS 10.15 o posterior |
| Apple | Capacidad Sign in with Apple en tu App ID |
| Clientes OAuth en la consola de Google Cloud |