Обзор
Большинство пользователей сдаются на форме регистрации: имя пользователя, пароль, который надо помнить, код из e-mail, попавший в спам. С KlugAuth они нажимают Продолжить через Apple или Продолжить через Google — и всё готово.
KlugAuth показывает нативный вход каждой платформы: окно Apple с Face ID / Touch ID на iOS и macOS, окно аккаунта Android (Credential Manager) для Google и системное окно входа для Google на iOS и macOS. Он возвращает токен идентификации провайдера вместе с вашим nonce, готовый к проверке на вашем сервере, а также код авторизации Apple, необходимый для отзыва связи при удалении аккаунта (правило App Store 5.1.1(v)).
Google SDK не включён: вход через Google на iOS и macOS использует стандартный процесс OAuth с PKCE в системном окне браузера, поэтому расширение остаётся небольшим.
KlugAuth работает в текущем выпуске наших приложений, нашего доказательства работоспособности, для регистрации, входа и подтверждения выхода с устройства через Apple или Google.
Возможности
- Автономность: один ANE, без базовой библиотеки и зависимых ANE
- Вход через Apple на iOS 13+, macOS 10.15+ и в приложениях iPad на Mac с Apple silicon
- Вход через Google на Android (Credential Manager) и на iOS / macOS (системное окно входа, без Google SDK)
- Токен идентификации, ID пользователя, e-mail и имя; код авторизации Apple для обновления и отзыва
- Помощник nonce для защиты от повторного воспроизведения (Apple передаёт его SHA-256, Google — исходное значение)
- Проверка состояния учётных данных Apple (авторизован / отозван) для вернувшихся пользователей
- Отдельные события успеха, отмены и ошибки; отмена сообщается отдельно и никогда не считается ошибкой
Поддерживаемые платформы
Вход через Apple на Android возможен через веб-процесс Apple и небольшую серверную страницу; мы можем предоставить её в рамках проекта. isSupported (Apple) и isGoogleSupported сообщают вашему коду, что предлагает устройство.
Начало работы
Добавьте расширение в дескриптор вашего приложения:
<extensions>
<extensionID>com.klug.auth.KlugAuth</extensionID>
</extensions>
Для входа через Apple добавьте entitlement (iOS: Entitlements в дескрипторе; macOS: при подписи):
<key>com.apple.developer.applesignin</key> <array><string>Default</string></array>
Для Google создайте клиенты OAuth в консоли Google Cloud: веб-клиент (его ID — аудитория токена на Android), клиент Android с именем вашего пакета и SHA-1 и клиент iOS для iOS и macOS.
Примеры кода
Пять полных сценариев — от кнопок до вашего сервера. Каждый вызов возвращается сразу; результаты приходят как KlugAuthEvent. Полная документация →
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
Обзор API
| KlugAuth.getInstance() | Возвращает единственный экземпляр. |
| isSupported | True там, где доступен вход через Apple (iOS, macOS). |
| isGoogleSupported | True там, где доступен вход через Google (Android, iOS, macOS). |
| generateNonce() | Статический. Новый случайный nonce (32 байта в hex); используйте один раз и отправьте то же значение на ваш сервер. |
| signInWithApple(nonce) | Открывает окно входа Apple. Возвращает false, если запуск не удался (не поддерживается или вход уже выполняется). |
| signInWithGoogle(clientId, nonce) | Открывает вход через Google. Android: ID веб-клиента; iOS / macOS: ID клиента iOS. Возвращает false, если запуск не удался. |
| getCredentialState(userID) | Спрашивает у Apple, авторизован ли пользователь по-прежнему; ответ приходит как APPLE_CREDENTIAL_STATE. iOS и macOS. |
| KlugAuthEvent | identityToken, authorizationCode, userID, email, givenName, familyName, fullName, state, errorCode, errorMessage. |
События
| APPLE_SUCCESS | identityToken, authorizationCode, userID; email и имена — только при первой авторизации. |
| APPLE_CANCELED | Пользователь закрыл окно. |
| APPLE_ERROR | errorCode и errorMessage от системы. |
| APPLE_CREDENTIAL_STATE | userID и state: authorized · revoked · notFound · transferred · unknown |
| GOOGLE_SUCCESS | identityToken, userID (e-mail аккаунта), email, givenName, familyName. |
| GOOGLE_CANCELED | Пользователь закрыл окно. |
| GOOGLE_ERROR | errorCode и errorMessage; на Android NO_ACCOUNT, если на устройстве нет аккаунта Google. |
Купить KlugAuth
Годовая лицензия на одно приложение AIR со всеми обновлениями в течение 12 месяцев. После оплаты вы получаете расширение, библиотеку ActionScript и документацию по e-mail, обычно в течение одного рабочего дня. Лицензия и условия
- Лицензия на одно приложение AIR
- Все обновления в течение 12 месяцев
- Без поддержки
- Лицензия на одно приложение AIR
- Все обновления в течение 12 месяцев
- Ответ по e-mail в течение 7 дней
- Лицензия на одно приложение AIR
- Все обновления в течение 12 месяцев
- Ответ по e-mail в течение 48 часов
Требования
| AIR SDK | 51.x (HARMAN) |
| iOS | iOS 13 или новее |
| Android | Android 6 или новее, службы Google Play |
| macOS | macOS 10.15 или новее |
| Apple | Возможность Sign in with Apple для вашего App ID |
| Клиенты OAuth в консоли Google Cloud |