Войдите в систему с помощью Credential Manager

Credential Manager — это API Jetpack, который поддерживает несколько методов входа, таких как имя пользователя и пароль, ключи доступа и интегрированные решения для входа (например, вход через Google) в одном API, что упрощает интеграцию для разработчиков.

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

На этой странице объясняется концепция паролей и шаги по реализации поддержки решений аутентификации на стороне клиента, включая пароли, с использованием API Credential Manager. Также доступна отдельная страница часто задаваемых вопросов с ответами на более подробные и конкретные вопросы.

О ключах доступа

Пароли — более безопасная и простая замена паролям. С помощью паролей пользователи могут входить в приложения и на веб-сайты с помощью биометрического датчика (например, отпечатка пальца или распознавания лица), PIN-кода или графического ключа. Это обеспечивает удобный вход, избавляя пользователей от необходимости запоминать имена пользователей и пароли.

Пароли основаны на стандарте WebAuthn (веб-аутентификация), совместно разработанном альянсом FIDO и консорциумом Всемирной паутины (W3C). WebAuthn использует криптографию с открытым ключом для аутентификации пользователя. Веб-сайт или приложение, в которое входит пользователь, может видеть и хранить открытый ключ, но не закрытый ключ. Закрытый ключ хранится в секрете и в безопасности. А поскольку ключ уникален и привязан к веб-сайту или приложению, пароли защищены от фишинга, что обеспечивает дополнительную безопасность.

Диспетчер учетных данных позволяет пользователям создавать ключи доступа и хранить их в диспетчере паролей Google .

Ознакомьтесь со статьей Аутентификация пользователей с помощью паролей, чтобы узнать, как реализовать бесперебойные потоки аутентификации с помощью паролей с помощью Credential Manager.

Предпосылки

Чтобы использовать диспетчер учетных данных, выполните действия, описанные в этом разделе.

Используйте последнюю версию платформы

Credential Manager поддерживается на устройствах Android 4.4 (уровень API 19) и выше.

Добавьте зависимости в ваше приложение

Добавьте следующие зависимости в скрипт сборки модуля вашего приложения:

implementation(libs.androidx.credentials)

// optional - needed for credentials support from play services, for devices running
// Android 13 and below.
implementation(libs.androidx.credentials.play.services.auth)

Узнайте больше о том, как сжать, скрыть и оптимизировать свое приложение .

Добавить поддержку ссылок на цифровые активы

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

  1. Создайте JSON-файл ссылок на цифровые активы. Например, чтобы указать, что веб-сайт https://signin.example.com и приложение Android с именем пакета com.example могут использовать одни и те же учётные данные для входа, создайте файл assetlinks.json со следующим содержимым:

    [
      {
        "relation" : [
          "delegate_permission/common.handle_all_urls",
          "delegate_permission/common.get_login_creds"
        ],
        "target" : {
          "namespace" : "android_app",
          "package_name" : "com.example.android",
          "sha256_cert_fingerprints" : [
            SHA_HEX_VALUE
          ]
        }
      }
    ]
    

    Поле relation представляет собой массив из одной или нескольких строк, описывающих объявляемую связь. Чтобы объявить, что приложения и сайты используют общие учётные данные для входа, укажите связи как delegate_permission/handle_all_urls и delegate_permission/common.get_login_creds .

    Поле target — это объект, определяющий актив, к которому относится декларация. Следующие поля идентифицируют веб-сайт:

    namespace web
    site

    URL-адрес веб-сайта в формате https:// domain [: optional_port ] ; например, https://www.example.com .

    domain должен быть полностью определен, а optional_port должен быть опущен при использовании порта 443 для HTTPS.

    Целевым site может быть только корневой домен: вы не можете ограничить связь приложения с конкретным подкаталогом. Не включайте путь в URL, например, косую черту в конце.

    Поддомены не считаются совпадающими: то есть, если вы указываете domain как www.example.com , домен www.counter.example.com не будет связан с вашим приложением.

    Следующие поля идентифицируют приложение Android:

    namespace android_app
    package_name Имя пакета, объявленное в манифесте приложения. Например, com.example.android
    sha256_cert_fingerprints Отпечатки пальцев SHA256 сертификата подписи вашего приложения.
  2. Разместите JSON-файл ссылки на цифровые активы в следующем месте на домене входа:

    https://domain[:optional_port]/.well-known/assetlinks.json
    

    Например, если ваш домен входа — signin.example.com , разместите JSON-файл по адресу https://signin.example.com/.well-known/assetlinks.json .

    Тип MIME для файла ссылки на цифровые активы должен быть JSON. Убедитесь, что сервер отправляет заголовок Content-Type: application/json в ответе.

  3. Убедитесь, что ваш хостинг-провайдер разрешает Google извлекать ваш файл Digital Asset Link. Если у вас есть файл robots.txt , он должен разрешать агенту Googlebot извлекать файлы /.well-known/assetlinks.json . Большинство сайтов позволяют любому автоматизированному агенту извлекать файлы по пути /.well-known/ , чтобы другие сервисы могли получить доступ к метаданным в этих файлах:

    User-agent: *
    Allow: /.well-known/
    
  4. Добавьте следующую строку в файл манифеста в разделе <application> :

    <meta-data android:name="asset_statements" android:resource="@string/asset_statements" />
    
  5. Если вы используете вход по паролю через диспетчер учётных данных, выполните этот шаг для настройки привязки цифровых активов в манифесте. Этот шаг пропускается, если вы используете только пароли.

    Объявите ассоциацию в приложении Android. Добавьте объект, указывающий файлы assetlinks.json для загрузки. Необходимо экранировать все апострофы и кавычки, используемые в строке. Например:

    <string name="asset_statements" translatable="false">
    [{
      \"include\": \"https://signin.example.com/.well-known/assetlinks.json\"
    }]
    </string>
    
    > GET /.well-known/assetlinks.json HTTP/1.1
    > User-Agent: curl/7.35.0
    > Host: signin.example.com
    
    < HTTP/1.1 200 OK
    < Content-Type: application/json
    

Настройте диспетчер учетных данных

Чтобы настроить и инициализировать объект CredentialManager , добавьте логику, подобную следующей:

// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)

Укажите поля учетных данных

В Android 14 и более поздних версиях атрибут isCredential может использоваться для указания полей учётных данных, таких как поля имени пользователя или пароля. Этот атрибут указывает, что данное представление представляет собой поле учётных данных, предназначенное для работы с Credential Manager и сторонними поставщиками учётных данных, а также помогает сервисам автозаполнения предоставлять более качественные предложения. Когда приложение использует API Credential Manager, отображается нижняя страница Credential Manager с доступными учётными данными, и нет необходимости отображать диалоговое окно автозаполнения для имени пользователя и пароля. Аналогичным образом, нет необходимости отображать диалоговое окно сохранения автозаполнения для паролей, поскольку приложение будет запрашивать API Credential Manager для сохранения учётных данных.

Чтобы использовать атрибут isCredential , добавьте его в соответствующие представления:

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:isCredential="true" />

Войдите в систему как пользователь

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

  1. Инициализируйте параметры аутентификации по паролю и ключу доступа:

    // Retrieves the user's saved password for your app from their
    // password provider.
    val getPasswordOption = GetPasswordOption()
    
    // Get passkey from the user's public key credential provider.
    val getPublicKeyCredentialOption = GetPublicKeyCredentialOption(
      requestJson = requestJson
    )
          
  2. Используйте параметры, полученные на предыдущем шаге, для создания запроса на вход.

    val credentialRequest = GetCredentialRequest(
      listOf(getPasswordOption, getPublicKeyCredentialOption),
    )
          
  3. Запустите процесс входа:

    coroutineScope {
      try {
        result = credentialManager.getCredential(
          // Use an activity-based context to avoid undefined system UI
          // launching behavior.
          context = activityContext,
          request = credentialRequest
        )
        handleSignIn(result)
      } catch (e: GetCredentialException) {
        // Handle failure
      }
    }
        
    fun handleSignIn(result: GetCredentialResponse) {
      // Handle the successfully returned credential.
      val credential = result.credential
    
      when (credential) {
        is PublicKeyCredential -> {
          val responseJson = credential.authenticationResponseJson
          // Share responseJson i.e. a GetCredentialResponse on your server to
          // validate and  authenticate
        }
    
        is PasswordCredential -> {
          val username = credential.id
          val password = credential.password
          // Use id and password to send to your server to validate
          // and authenticate
        }
    
        is CustomCredential -> {
          // If you are also using any external sign-in libraries, parse them
          // here with the utility functions provided.
          if (credential.type == ExampleCustomCredential.TYPE) {
            try {
              val ExampleCustomCredential =
                ExampleCustomCredential.createFrom(credential.data)
              // Extract the required credentials and complete the authentication as per
              // the federated sign in or any external sign in library flow
            } catch (e: ExampleCustomCredential.ExampleCustomCredentialParsingException) {
              // Unlikely to happen. If it does, you likely need to update the dependency
              // version of your external sign-in library.
              Log.e(TAG, "Failed to parse an ExampleCustomCredential", e)
            }
          } else {
            // Catch any unrecognized custom credential type here.
            Log.e(TAG, "Unexpected type of credential")
          }
        }
        else -> {
          // Catch any unrecognized credential type here.
          Log.e(TAG, "Unexpected type of credential")
        }
      }
    }
        

В следующем примере показано, как форматировать JSON-запрос при получении ключа доступа:

{
  "challenge": "T1xCsnxM2DNL2KdK5CLa6fMhD7OBqho6syzInk_n-Uo",
  "allowCredentials": [],
  "timeout": 1800000,
  "userVerification": "required",
  "rpId": "https://passkeys-codelab.glitch.me/"
}

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

{
  "id": "KEDetxZcUfinhVi6Za5nZQ",
  "type": "public-key",
  "rawId": "KEDetxZcUfinhVi6Za5nZQ",
  "response": {
    "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiVDF4Q3NueE0yRE5MMktkSzVDTGE2Zk1oRDdPQnFobzZzeXpJbmtfbi1VbyIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOk1MTHpEdll4UTRFS1R3QzZVNlpWVnJGUXRIOEdjVi0xZDQ0NEZLOUh2YUkiLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJjb20uZ29vZ2xlLmNyZWRlbnRpYWxtYW5hZ2VyLnNhbXBsZSJ9",
    "authenticatorData": "j5r_fLFhV-qdmGEwiukwD5E_5ama9g0hzXgN8thcFGQdAAAAAA",
    "signature": "MEUCIQCO1Cm4SA2xiG5FdKDHCJorueiS04wCsqHhiRDbbgITYAIgMKMFirgC2SSFmxrh7z9PzUqr0bK1HZ6Zn8vZVhETnyQ",
    "userHandle": "2HzoHm_hY0CjuEESY9tY6-3SdjmNHOoNqaPDcZGzsr0"
  }
}

Обрабатывать исключения, когда учетные данные недоступны

В некоторых случаях у пользователя может не быть доступных учётных данных или пользователь может не дать согласия на использование доступных учётных данных. Если при вызове метода getCredential() учётные данные не найдены, возвращается исключение NoCredentialException . В этом случае ваш код должен обрабатывать экземпляры NoCredentialException .

coroutineScope {
  try {
    result = credentialManager.getCredential(
      context = activityContext,
      request = credentialRequest
    )
  } catch (e: GetCredentialException) {
    Log.e("CredentialManager", "No credential available", e)
  }
}

На устройствах с Android 14 и выше можно уменьшить задержку при отображении селектора учетных записей, используя метод prepareGetCredential() перед вызовом getCredential() .

coroutineScope {
  val response = credentialManager.prepareGetCredential(
    GetCredentialRequest(
      listOf(
        getPublicKeyCredentialOption,
        getPasswordOption
      )
    )
  )
}

Метод prepareGetCredential() не вызывает элементы пользовательского интерфейса. Он лишь помогает выполнить подготовительную работу, чтобы впоследствии можно было запустить оставшуюся операцию получения учётных данных (с использованием пользовательского интерфейса) через API getCredential() .

Кэшированные данные возвращаются в объекте PrepareGetCredentialResponse . Если учётные данные существуют, результаты будут кэшированы, и позже вы сможете запустить оставшийся API getCredential() , чтобы открыть селектор учётных записей с кэшированными данными.

Регистрационные потоки

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

Создать ключ доступа

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

suspend fun createPasskey(requestJson: String, preferImmediatelyAvailableCredentials: Boolean) {
  val createPublicKeyCredentialRequest = CreatePublicKeyCredentialRequest(
    // Contains the request in JSON format. Uses the standard WebAuthn
    // web JSON spec.
    requestJson = requestJson,
    // Defines whether you prefer to use only immediately available
    // credentials, not hybrid credentials, to fulfill this request.
    // This value is false by default.
    preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials,
  )

  // Execute CreateCredentialRequest asynchronously to register credentials
  // for a user account. Handle success and failure cases with the result and
  // exceptions, respectively.
  coroutineScope {
    try {
      val result = credentialManager.createCredential(
        // Use an activity-based context to avoid undefined system
        // UI launching behavior
        context = activityContext,
        request = createPublicKeyCredentialRequest,
      )
      //  Handle passkey creation result
    } catch (e : CreateCredentialException){
      handleFailure(e)
    }
  }
}
fun handleFailure(e: CreateCredentialException) {
  when (e) {
    is CreatePublicKeyCredentialDomException -> {
      // Handle the passkey DOM errors thrown according to the
      // WebAuthn spec.
    }
    is CreateCredentialCancellationException -> {
      // The user intentionally canceled the operation and chose not
      // to register the credential.
    }
    is CreateCredentialInterruptedException -> {
      // Retry-able error. Consider retrying the call.
    }
    is CreateCredentialProviderConfigurationException -> {
      // Your app is missing the provider configuration dependency.
      // Most likely, you're missing the
      // "credentials-play-services-auth" module.
    }
    is CreateCredentialCustomException -> {
      // You have encountered an error from a 3rd-party SDK. If you
      // make the API call with a request object that's a subclass of
      // CreateCustomCredentialRequest using a 3rd-party SDK, then you
      // should check for any custom exception type constants within
      // that SDK to match with e.type. Otherwise, drop or log the
      // exception.
    }
    else -> Log.w(TAG, "Unexpected exception type ${e::class.java.name}")
  }
}

Форматируйте JSON-запрос

После создания ключа доступа необходимо связать его с учётной записью пользователя и сохранить открытый ключ на сервере. В следующем примере кода показано, как форматировать JSON-запрос при создании ключа доступа.

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

{
  "challenge": "abc123",
  "rp": {
    "name": "Credential Manager example",
    "id": "credential-manager-test.example.com"
  },
  "user": {
    "id": "def456",
    "name": "helloandroid@gmail.com",
    "displayName": "helloandroid@gmail.com"
  },
  "pubKeyCredParams": [
    {
      "type": "public-key",
      "alg": -7
    },
    {
      "type": "public-key",
      "alg": -257
    }
  ],
  "timeout": 1800000,
  "attestation": "none",
  "excludeCredentials": [
    {
      "id": "ghi789",
      "type": "public-key"
    },
    {
      "id": "jkl012",
      "type": "public-key"
    }
  ],
  "authenticatorSelection": {
    "authenticatorAttachment": "platform",
    "requireResidentKey": true,
    "residentKey": "required",
    "userVerification": "required"
  }
}

Установите значения для authenticatorAttachment

Параметр authenticatorAttachment можно задать только при создании учётных данных. Можно указать platform , cross-platform или не указывать значение. В большинстве случаев рекомендуется не указывать значение.

  • platform : Чтобы зарегистрировать текущее устройство пользователя или предложить пользователю пароля обновиться до ключей доступа после входа в систему, установите authenticatorAttachment на platform .
  • cross-platform : это значение обычно используется при регистрации многофакторных учетных данных и не применяется в контексте ключа доступа.
  • Нет значения : чтобы предоставить пользователям возможность гибко создавать ключи доступа на предпочитаемых ими устройствах (например, в настройках учётной записи), параметр authenticatorAttachment не следует указывать при добавлении ключа доступа. В большинстве случаев наилучшим вариантом будет оставить этот параметр неуказанным.

Предотвратить создание дубликатов ключей доступа

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

Обработка ответа JSON

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

{
  "id": "KEDetxZcUfinhVi6Za5nZQ",
  "type": "public-key",
  "rawId": "KEDetxZcUfinhVi6Za5nZQ",
  "response": {
    "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoibmhrUVhmRTU5SmI5N1Z5eU5Ka3ZEaVh1Y01Fdmx0ZHV2Y3JEbUdyT0RIWSIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOk1MTHpEdll4UTRFS1R3QzZVNlpWVnJGUXRIOEdjVi0xZDQ0NEZLOUh2YUkiLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJjb20uZ29vZ2xlLmNyZWRlbnRpYWxtYW5hZ2VyLnNhbXBsZSJ9",
    "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViUj5r_fLFhV-qdmGEwiukwD5E_5ama9g0hzXgN8thcFGRdAAAAAAAAAAAAAAAAAAAAAAAAAAAAEChA3rcWXFH4p4VYumWuZ2WlAQIDJiABIVgg4RqZaJyaC24Pf4tT-8ONIZ5_Elddf3dNotGOx81jj3siWCAWXS6Lz70hvC2g8hwoLllOwlsbYatNkO2uYFO-eJID6A"
  }
}

Проверка источника на основе клиентских данных JSON

origin представляет собой приложение или веб-сайт, с которого поступает запрос, и используется ключами доступа для защиты от фишинговых атак. Сервер вашего приложения должен проверять источник клиентских данных по списку разрешённых приложений и веб-сайтов. Если сервер получает запрос от приложения или веб-сайта из неизвестного источника, такой запрос должен быть отклонён.

В случае веб-сайта origin соответствует тому же сайту , где был выполнен вход с использованием учетных данных. Например, если URL-адрес https://www.example.com:8443/store?category=shoes#athletic , origin будет https://www.example.com:8443 .

Для приложений Android пользовательский агент автоматически устанавливает origin на основе подписи вызывающего приложения. Эта подпись должна быть проверена на соответствие на вашем сервере для проверки подлинности вызывающего API ключа доступа. origin Android — это URI, полученный из хеша SHA-256 сертификата подписи APK, например:

android:apk-key-hash:<sha256_hash-of-apk-signing-cert>

Хэши SHA-256 сертификатов подписи из хранилища ключей можно найти, выполнив следующую команду терминала:

keytool -list -keystore <path-to-apk-signing-keystore>

Хэши SHA-256 представлены в шестнадцатеричном формате, разделённом двоеточиями ( 91:F7:CB:F9:D6:81… ), а значения origin Android закодированы в формате base64url. Этот пример на Python демонстрирует, как преобразовать хеш-формат в совместимый шестнадцатеричный формат, разделённый двоеточиями:

import binascii
import base64
fingerprint = '91:F7:CB:F9:D6:81:53:1B:C7:A5:8F:B8:33:CC:A1:4D:AB:ED:E5:09:C5'
print("android:apk-key-hash:" + base64.urlsafe_b64encode(binascii.a2b_hex(fingerprint.replace(':', ''))).decode('utf8').replace('=', ''))

Замените значение fingerprint своим собственным. Вот пример результата:

android:apk-key-hash:kffL-daBUxvHpY-4M8yhTavt5QnFEI2LsexohxrGPYU

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

Сохранить пароль пользователя

Если пользователь предоставляет имя пользователя и пароль для аутентификации в вашем приложении, вы можете зарегистрировать учётные данные пользователя, которые будут использоваться для его аутентификации. Для этого создайте объект CreatePasswordRequest :

suspend fun registerPassword(username: String, password: String) {
  // Initialize a CreatePasswordRequest object.
  val createPasswordRequest =
    CreatePasswordRequest(id = username, password = password)

  // Create credential and handle result.
  coroutineScope {
    try {
      val result =
        credentialManager.createCredential(
          // Use an activity based context to avoid undefined
          // system UI launching behavior.
          activityContext,
          createPasswordRequest
        )
      // Handle register password result
    } catch (e: CreateCredentialException) {
      handleFailure(e)
    }
  }
}

Поддержка восстановления учетных данных

Если у пользователя больше нет доступа к устройству, на котором он хранил свои учётные данные, ему может потребоваться восстановление данных из защищённой онлайн-резервной копии. Подробнее о восстановлении учётных данных см. в разделе «Восстановление доступа или добавление новых устройств» этой записи блога: Безопасность паролей в Менеджере паролей Google .

Автоматически создавать ключи доступа для пользователей

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

CreatePublicKeyCredentialRequest(
    // other parameters
    isConditionalCreateRequest: Boolean = true
)

При входе пользователя в систему автоматически создаётся ключ доступа, который сохраняется в выбранном менеджере паролей. При использовании Google Password Manager пользователь должен использовать пароль, сохранённый в менеджере паролей (с помощью менеджера учётных данных или автозаполнения). Пользователь получает уведомление о создании ключа доступа и может перейти в менеджер паролей для управления им.

Для этой функции требуется версия 1.6.0-alpha01 или выше.

Добавить поддержку инструментов управления паролями с конечными точками ключей доступа и известными URL-адресами.

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

  1. Для проверяющей стороны по адресу https://example.com , у которой есть веб-сайт и приложения для Android и iOS, известным URL-адресом будет https://example.com/.well-known/passkey-endpoints .
  2. При запросе URL-адреса ответ должен использовать следующую схему

    {
      "enroll": "https://example.com/account/manage/passkeys/create"
      "manage": "https://example.com/account/manage/passkeys"
    }
    
  3. Чтобы эта ссылка открывалась непосредственно в вашем приложении, а не в Интернете, используйте ссылки приложений Android .

  4. Более подробную информацию можно найти в известном объяснении URL-адресов конечных точек ключа на GitHub.

Помогите пользователям управлять своими ключами доступа, указав, какой провайдер их создал

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

Например, если пользователь создаёт ключ доступа на устройстве Android с помощью Google Password Manager, проверяющая сторона получает AAGUID, который выглядит примерно так: «ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4». Проверяющая сторона может добавить аннотацию ключа доступа в список ключей доступа, чтобы указать, что он был создан с помощью Google Password Manager.

Чтобы сопоставить AAGUID с поставщиком ключей доступа, RP могут использовать репозиторий AAGUID, созданный сообществом . Найдите AAGUID в списке, чтобы найти имя и значок поставщика ключей доступа.

Узнайте больше об интеграции AAGUID .

Устранение распространенных ошибок

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

Дополнительные ресурсы

Чтобы узнать больше об API диспетчера учетных данных и ключах доступа, просмотрите следующие ресурсы: