Аутентификация на носимых устройствах

Приложения Wear OS могут работать автономно, без сопутствующего приложения. Это означает, что приложению Wear OS необходимо самостоятельно управлять аутентификацией при доступе к данным из Интернета. Но небольшой размер экрана часов и ограниченные возможности ввода ограничивают возможности аутентификации, которые может использовать приложение Wear OS.

В этом руководстве описаны рекомендуемые методы аутентификации для приложений Wear OS, а также альтернативные методы, если эти методы не подходят для сценария использования приложения.

Чтобы узнать больше о том, как создать удобный процесс входа в систему, ознакомьтесь с руководством по пользовательскому интерфейсу входа .

Гостевой режим

Не требует аутентификации для всех функций. Вместо этого предоставьте пользователю как можно больше функций, не требуя от него входа в систему.

Пользователи могут обнаружить и установить ваше приложение Wear, не используя мобильное приложение, поэтому у них может не быть учетной записи, и они могут не знать, какие функции оно предлагает. Убедитесь, что гостевой режим точно отображает возможности вашего приложения.

Некоторые устройства могут оставаться разблокированными дольше

На поддерживаемых устройствах под управлением Wear OS 5 или более поздней версии система определяет, носит ли пользователь устройство на запястье. Если пользователь выключает обнаружение запястья, а затем снимает устройство с запястья, система сохраняет устройство разблокированным в течение более длительного периода времени, чем в противном случае.

Если вашему приложению требуется более высокий уровень безопасности (например, при отображении потенциально конфиденциальных или личных данных), сначала проверьте, включено ли обнаружение запястья:

val wristDetectionEnabled =
        isWristDetectionAutoLockingEnabled(applicationContext)

Если возвращаемое значение этого метода — false , предложите пользователю войти в учетную запись в вашем приложении, прежде чем отображать пользовательский контент.

Рекомендуемые методы аутентификации

Используйте следующие методы аутентификации, чтобы позволить автономным приложениям Wear OS получать учетные данные для аутентификации пользователя.

Передача токенов с использованием уровня данных

Приложение-компаньон телефона может безопасно передавать данные аутентификации в приложение Wear OS с помощью уровня носимых данных. Передавайте учетные данные в виде сообщений или элементов данных.

Этот тип аутентификации обычно не требует от пользователя каких-либо действий. Однако избегайте выполнения аутентификации, не сообщая пользователю о том, что он входит в систему. Вы можете сообщить пользователю, используя простой, закрывающийся экран, который показывает ему, что его учетная запись переносится с мобильного телефона.

Важно! Ваше приложение Wear должно предлагать хотя бы еще один метод аутентификации, поскольку этот вариант работает только на часах, сопряженных с Android, когда установлено соответствующее мобильное приложение. Предоставьте альтернативный метод аутентификации для пользователей, у которых нет соответствующего мобильного приложения или чье устройство Wear OS сопряжено с устройством iOS.

Передавайте токены, используя уровень данных из мобильного приложения, как показано в следующем примере:

val token = "..." // Auth token to transmit to the wearable device.
val dataClient: DataClient = Wearable.getDataClient(context)
val putDataReq: PutDataRequest = PutDataMapRequest.create("/auth").run {
    dataMap.putString("token", token)
    asPutDataRequest()
}
val putDataTask: Task<DataItem> = dataClient.putDataItem(putDataReq)

Прослушивайте события изменения данных в приложении часов, как показано в следующем примере:

val dataClient: DataClient = Wearable.getDataClient(context)
dataClient.addListener{ dataEvents ->
    dataEvents.forEach { event ->
        if (event.type == DataEvent.TYPE_CHANGED) {
            val dataItemPath = event.dataItem.uri.path ?: ""
            if (dataItemPath.startsWith("/auth")) {
                val token = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("token")
                // Display interstitial screen to notify the user they are being signed in.
                // Then, store the token and use it in network requests.
            }
        }
    }
}

Дополнительные сведения об использовании уровня данных носимых устройств см. в разделе Отправка и синхронизация данных на Wear OS .

Используйте OAuth 2.0.

Wear OS поддерживает два потока на основе OAuth 2.0, которые описаны в следующих разделах:

  • Предоставление кода авторизации с ключом подтверждения для обмена кодами (PKCE), как определено в RFC 7636.
  • Предоставление авторизации устройства, как определено в RFC 8628.

Примечание. Чтобы гарантировать, что ваше приложение не выключится, когда часы перейдут в внешний режим, включите Always-on с помощью AmbientModeSupport.attach в действии, выполняющем аутентификацию. Дополнительные сведения о рекомендациях по работе в Ambient Mode см. в разделе Обеспечьте видимость вашего приложения на Wear .

Ключ подтверждения для обмена кодами (PKCE)

Чтобы эффективно использовать PKCE, используйте RemoteAuthClient .

Чтобы выполнить запрос аутентификации из приложения Wear OS к поставщику OAuth, создайте объект OAuthRequest . Этот объект состоит из URL-адреса вашей конечной точки OAuth для получения токена и объекта CodeChallenge . В следующем коде показан пример создания запроса аутентификации:

val request = OAuthRequest.Builder(this.applicationContext)
    .setAuthProviderUrl(Uri.parse("https://...."))
    .setClientId(clientId)
    .setCodeChallenge(codeChallenge)
    .build()

После создания запроса аутентификации отправьте его сопутствующему приложению с помощью метода sendAuthorizationRequest() :

val client = RemoteAuthClient.create(this)
client.sendAuthorizationRequest(request,
    { command -> command?.run() },
    object : RemoteAuthClient.Callback() {
        override fun onAuthorizationResponse(
            request: OAuthRequest,
            response: OAuthResponse
        ) {
            // Extract the token from the response, store it and use it in network requests.
        }

        override fun onAuthorizationError(errorCode: Int) {
            // Handle error
        }
    }
)

Этот запрос вызывает вызов сопутствующего приложения, которое затем отображает пользовательский интерфейс авторизации в веб-браузере на мобильном телефоне пользователя. Поставщик OAuth 2.0 проверяет подлинность пользователя и получает согласие пользователя на запрошенные разрешения. Ответ отправляется на автоматически созданный URL-адрес перенаправления.

После успешной или неудачной авторизации сервер OAuth 2.0 перенаправляет на URL-адрес, указанный в запросе. Если пользователь одобряет запрос на доступ, то ответ содержит код авторизации. Если пользователь не одобряет запрос, ответ содержит сообщение об ошибке.

Ответ имеет форму строки запроса и выглядит как один из следующих примеров:

  https://wear.googleapis.com/3p_auth/com.your.package.name?code=xyz
  https://wear.googleapis-cn.com/3p_auth/com.your.package.name?code=xyz

При этом загружается страница, которая направляет пользователя к сопутствующему приложению. Сопутствующее приложение проверяет URL-адрес ответа и передает ответ стороннему приложению для просмотра с помощью API onAuthorizationResponse .

Затем приложение часов может обменять код авторизации на токен доступа.

Примечание. После создания OAuthRequest вы сможете найти URL-адрес перенаправления, открыв redirectUrl .

Предоставление авторизации устройства

При использовании разрешения на авторизацию устройства пользователь открывает URI проверки на другом устройстве. Затем сервер авторизации просит их одобрить или отклонить запрос.

Чтобы упростить этот процесс, используйте RemoteActivityHelper , чтобы открыть веб-страницу на сопряженном мобильном устройстве пользователя, как показано в следующем примере:

// Request access from the authorization server and receive Device Authorization Response.
val verificationUri = "..." // Extracted from the Device Authorization Response.
RemoteActivityHelper.startRemoteActivity(
    this,
    Intent(Intent.ACTION_VIEW)
        .addCategory(Intent.CATEGORY_BROWSABLE)
        .setData(Uri.parse(verificationUri)),
    null
)
// Poll the authorization server to find out if the user completed the user authorization
// step on their mobile device.

Если у вас есть приложение для iOS, используйте универсальные ссылки , чтобы перехватить это намерение в своем приложении, вместо того, чтобы полагаться на браузер для авторизации токена.

Другие методы аутентификации

Wear OS поддерживает дополнительные методы входа, описанные в следующих разделах.

Вход в Google

Вход в Google позволяет пользователю войти в систему, используя существующую учетную запись Google. Он предлагает лучший пользовательский опыт и прост в поддержке, особенно если вы уже внедрили его в свои портативные приложения.

После описанных ранее рекомендуемых методов аутентификации вход в Google является следующим предпочтительным решением, поскольку он также хорошо работает на iOS. В следующем разделе описывается, как выполнить базовую интеграцию входа в Google.

Предварительные условия

Прежде чем вы сможете начать интеграцию входа в Google в свое приложение Wear OS, вам необходимо настроить проект консоли Google API и проект Android Studio. Дополнительную информацию см. в разделе «Начать интеграцию входа в Google в ваше приложение для Android» .

Если вы используете вход в Google с приложением или сайтом, который взаимодействует с внутренним сервером, существуют два дополнительных обязательных условия:

  • Создайте идентификатор клиента веб-приложения OAuth 2.0 для своего внутреннего сервера. Этот идентификатор клиента отличается от идентификатора клиента вашего приложения. Дополнительные сведения см. в разделе Включение доступа на стороне сервера .
  • Надежно определите текущего пользователя, вошедшего в систему, на сервере, отправив токен идентификатора пользователя по протоколу HTTPS. Чтобы узнать, как аутентифицировать пользователя на внутреннем сервере, см. Аутентификация на внутреннем сервере .

Интегрируйте вход в Google в свое приложение

Просмотрите и выполните следующие действия, которые подробно описаны в следующих разделах, чтобы интегрировать вход в Google в приложение Wear OS:

  1. Настройте вход в Google .
  2. Добавьте кнопку входа в Google .
  3. Запустите процесс входа при нажатии кнопки входа .

Настройте вход в Google и создайте объект GoogleApiClient.

В методе onCreate() вашего действия входа настройте вход в Google для запроса пользовательских данных, необходимых вашему приложению. Затем создайте объект GoogleApiClient с доступом к API входа в Google и указанными вами параметрами. Эти шаги показаны в следующем примере:

public class MyNewActivity extends AppCompatActivity {

    private static final int RC_SIGN_IN = 9001;

    private GoogleSignInClient mSignInClient;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        GoogleSignInOptions options =
                new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                        .build();

        mSignInClient = GoogleSignIn.getClient(this, options);
    }
}

Добавьте кнопку входа в Google в свое приложение

Выполните следующие шаги, чтобы добавить кнопку входа в Google:

  1. Добавьте SignInButton в макет вашего приложения:
  2.  <com.google.android.gms.common.SignInButton
     android:id="@+id/sign_in_button"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content" />
    
  3. В методе onCreate() вашего приложения зарегистрируйте OnClickListener вашей кнопки, чтобы регистрировать пользователя при нажатии:
  4. Котлин

    findViewById<View>(R.id.sign_in_button).setOnClickListener(this)
    

    Ява

    findViewById(R.id.sign_in_button).setOnClickListener(this);
    

Создайте намерение входа и запустите процесс входа.

Обрабатывайте нажатия кнопок входа в методе onCLick() создавая намерение входа с помощью метода getSignInIntent() . Затем запустите намерение с помощью метода startActivityForResult() .

Intent intent = mSignInClient.getSignInIntent();
startActivityForResult(intent, RC_SIGN_IN);

Пользователю предлагается выбрать учетную запись Google для входа. Если вы запросили области, выходящие за рамки профиля, электронной почты и открытого идентификатора, пользователю также будет предложено предоставить доступ к этим ресурсам.

Наконец, в методе onActivityResult действия получите результат входа с помощью getSignInResultFromIntent . После получения результата входа вы можете проверить, был ли вход успешным, с помощью метода isSuccess . Если вход успешен, вы можете вызвать метод getSignInAccount , чтобы получить объект GoogleSignInAccount , содержащий информацию о вошедшем в систему пользователе, например имя пользователя. Эти шаги показаны в следующем примере:

Котлин

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    super.onActivityResult(requestCode, resultCode, data)

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...).
    if (requestCode == RC_SIGN_IN) {
        Auth.GoogleSignInApi.getSignInResultFromIntent(data)?.apply {
            if (isSuccess) {
                // Get account information.
                fullName = signInAccount?.displayName
                mGivenName = signInAccount?.givenName
                mFamilyName = signInAccount?.familyName
                mEmail = signInAccount?.email
            }
        }
    }
}

Ява

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...).
    if (requestCode == RC_SIGN_IN) {
        GoogleSignInResult signInResult = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        if (signInResult.isSuccess()) {
            GoogleSignInAccount acct = signInResult.getSignInAccount();

            // Get account information.
            fullName = acct.getDisplayName();
            givenName = acct.getGivenName();
            familyName = acct.getFamilyName();
            email = acct.getEmail();
        }
    }
}

Чтобы увидеть пример приложения, реализующего вход в Google, см. пример входа в Google для часового специалиста на GitHub.

Аутентификация по индивидуальному коду

В качестве альтернативы описанным ранее методам аутентификации вы можете потребовать от пользователя пройти аутентификацию с другого устройства, например мобильного телефона или планшета, и получить кратковременный цифровой код. Затем пользователь вводит код на своем устройстве Wear OS, чтобы подтвердить свою личность, и получает токен аутентификации.

Этот поток аутентификации либо использует модуль входа вашего приложения, либо вручную интегрирует метод входа стороннего поставщика аутентификации в код вашего приложения. Хотя этот метод аутентификации требует ручной работы и дополнительных усилий, чтобы сделать его более безопасным, вы можете использовать этот метод, если вам потребуется аутентификация ранее в автономных приложениях Wear OS.

Поток аутентификации для этой настройки работает следующим образом:

  1. Пользователь выполняет действие с приложением Wear OS, требующее авторизации.
  2. Приложение Wear OS отображает пользователю экран аутентификации и предлагает пользователю ввести код с указанного URL-адреса.
  3. Пользователь переключается на мобильное устройство, планшет или ПК, а затем запускает браузер, переходит по URL-адресу, указанному в приложении Wear OS, и входит в систему.
  4. Пользователь получает кратковременный цифровой код, который он вводит на экране аутентификации приложения Wear OS с помощью встроенной клавиатуры в Wear OS:

  5. С этого момента вы можете использовать введенный код в качестве доказательства того, что это правильный пользователь, и обменять код на токен аутентификации, хранящийся и защищенный на устройстве Wear OS, для дальнейших аутентифицированных вызовов.

Примечание. Код, создаваемый пользователем, должен быть чисто числовым и не может содержать буквенных символов.

Этот поток аутентификации изображен на следующей диаграмме: