Android 15에서 인증 관리자는 사용자 인증 정보 생성 및 검색을 위한 싱글 탭 흐름을 지원합니다. 이 흐름에서는 생성되거나 사용되는 사용자 인증 정보의 정보가 더 많은 옵션의 진입점과 함께 생체 인식 프롬프트에 직접 표시됩니다. 이 간소화된 프로세스를 통해 사용자 인증 정보 생성 및 검색 프로세스가 더 효율적이고 간소화됩니다.
요구사항:
사용자의 기기에 생체 인식이 설정되어 있고 사용자가 애플리케이션 인증을 위해 생체 인식을 허용합니다.
로그인 흐름의 경우 이 기능은 계정에 사용할 수 있는 사용자 인증 정보 (예: 패스키 및 비밀번호)가 여러 개 있더라도 단일 계정 시나리오에서만 사용 설정됩니다.
패스키 생성 흐름에서 싱글 탭 사용 설정
이 메서드의 생성 단계는 기존 사용자 인증 정보 생성 프로세스와 일치합니다. BeginCreatePublicKeyCredentialRequest 내에서 패스키 요청인 경우 handleCreatePasskeyQuery()를 사용하여 요청을 처리합니다.
isBeginCreatePublicKeyCredentialRequest->{Log.i(TAG,"Request is passkey type")returnhandleCreatePasskeyQuery(request,passwordCount,passkeyCount)}
인증 제공자는 BiometricPromptData 인스턴스에서 allowedAuthenticator 속성을 명시적으로 설정해야 합니다. 이 속성을 설정하지 않으면 기본값은 DEVICE_WEAK입니다. 사용 사례에 필요한 경우 선택사항인 cryptoObject 속성을 설정합니다.
로그인 패스키 흐름에서 탭 한 번 사용 설정
패스키 생성 흐름과 마찬가지로 사용자 로그인 처리를 위한 기존 설정을 따릅니다. BeginGetPublicKeyCredentialOption에서 populatePasskeyData()를 사용하여 인증 요청에 관한 관련 정보를 수집합니다.
isBeginGetPublicKeyCredentialOption->{// ... other logicpopulatePasskeyData(origin,option,responseBuilder,autoSelectEnabled,allowedAuthenticator)// ... other logic as needed}
CreateEntry와 마찬가지로 BiometricPromptData 인스턴스가 PublicKeyCredentialEntry 인스턴스로 설정됩니다. 명시적으로 설정하지 않으면 allowedAuthenticator의 기본값은 BIOMETRIC_WEAK입니다.
PublicKeyCredentialEntry(// other properties...biometricPromptData=BiometricPromptData(allowedAuthenticators=allowedAuthenticator))
사용자 인증 정보 입력 선택 처리
패스키 생성 또는 로그인 중 패스키 선택을 위한 사용자 인증 정보 항목 선택을 처리하는 동안 적절한 PendingIntentHandler's
retrieveProviderCreateCredentialRequest 또는 retrieveProviderGetCredentialRequest를 호출합니다. 이러한 함수는 제공업체에 필요한 메타데이터가 포함된 객체를 반환합니다. 예를 들어 패스키 생성 항목 선택을 처리할 때 다음과 같이 코드를 업데이트합니다.
valcreateRequest=PendingIntentHandler.retrieveProviderCreateCredentialRequest(intent)if(createRequest==null){Log.i(TAG,"request is null")setUpFailureResponseAndFinish("Unable to extract request from intent")return}// Other logic...valbiometricPromptResult=createRequest.biometricPromptResult// Add your logic based on what needs to be done// after getting biometricsif(createRequest.callingRequestisCreatePublicKeyCredentialRequest){valpublicKeyRequest:CreatePublicKeyCredentialRequest=createRequest.callingRequestasCreatePublicKeyCredentialRequestif(biometricPromptResult==null){// Do your own authentication flow, if needed}elseif(biometricPromptResult.isSuccessful){createPasskey(publicKeyRequest.requestJson,createRequest.callingAppInfo,publicKeyRequest.clientDataHash,accountId)}else{valerror=biometricPromptResult.authenticationError// Process the error}// Other logic...}
마찬가지로 retrieveProviderGetCredentialRequest 중에 메타데이터를 추출합니다.
생체 인식 흐름이 null인지 확인합니다. 예인 경우 인증을 위해 자체 생체 인식을 구성합니다. 이는 작업 가져오기가 계측되는 방식과 유사합니다.
valgetRequest=PendingIntentHandler.retrieveProviderGetCredentialRequest(intent)if(getRequest==null){Log.i(TAG,"request is null")setUpFailureResponseAndFinish("Unable to extract request from intent")return}// Other logic...valbiometricPromptResult=getRequest.biometricPromptResult// Add your logic based on what needs to be done// after getting biometricsif(biometricPromptResult==null){// Do your own authentication flow, if necessary}elseif(biometricPromptResult.isSuccessful){Log.i(TAG,"The response from the biometricPromptResult was ${biometricPromptResult.authenticationResult?.authenticationType}")validatePasskey(publicKeyRequest.requestJson,origin,packageName,uid,passkey.username,credId,privateKey)}else{valerror=biometricPromptResult.authenticationError// Process the error}// Other logic...
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-08-27(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-08-27(UTC)"],[],[],null,["# Integrate single tap passkey creation and sign-in with biometric prompts\n\nOn Android 15, Credential Manager supports a single tap flow for credential\ncreation and retrieval. In this flow, the information of the credential being\ncreated, or being used, is displayed directly in the Biometric Prompt, along\nwith an entrypoint to more options. This simplified process creates a more\nefficient and streamlined credential creation and retrieval process.\n\n**Requirements:**\n\n- Biometrics have been set up on the user's device and the user allows them for authentication into applications.\n- For sign-in flows, this feature is enabled for single account scenarios only, even if there's multiple credentials (such as passkey and password) available for that account.\n\nEnable single tap on passkey creation flows\n-------------------------------------------\n\nThis method's creation steps match the [existing credential creation\nprocess](/identity/sign-in/credential-provider#handle-passkey-creation). Within your `BeginCreatePublicKeyCredentialRequest`, use\n`handleCreatePasskeyQuery()` to process the request if it is for a passkey. \n\n is BeginCreatePublicKeyCredentialRequest -\u003e {\n Log.i(TAG, \"Request is passkey type\")\n return handleCreatePasskeyQuery(request, passwordCount, passkeyCount)\n }\n\nIn your `handleCreatePasskeyQuery()`, include [`BiometricPromptData`](/reference/kotlin/androidx/credentials/provider/BiometricPromptData) with\nthe `CreateEntry` class: \n\n val createEntry = CreateEntry(\n // Additional properties...\n biometricPromptData = BiometricPromptData(\n allowedAuthenticators = allowedAuthenticator\n ),\n )\n\nCredential providers should explicitly set the `allowedAuthenticator` property\nin the `BiometricPromptData` instance. If this property is not set, the value\ndefaults to `DEVICE_WEAK`. Set the optional `cryptoObject` property if needed\nfor your use case.\n| **Note:** If the device is configured to use `DEVICE_CREDENTIALS` to require a PIN or passcode for authentication---regardless of whether biometrics are available or enabled---the standard credential manager flow will be used instead of the single-tap flow. This means the provider will always receive a `null` value for `biometricPromptResult` in these scenarios.\n\nEnable single tap on sign-in passkey flows\n------------------------------------------\n\nSimilar to the passkey creation flow, this will follow the existing setup for\n[handling user sign-in](/identity/sign-in/credential-provider#handle-user-sign-in). Under the `BeginGetPublicKeyCredentialOption`, use\n`populatePasskeyData()` to gather the relevant information about the\nauthentication request: \n\n is BeginGetPublicKeyCredentialOption -\u003e {\n // ... other logic\n\n populatePasskeyData(\n origin,\n option,\n responseBuilder,\n autoSelectEnabled,\n allowedAuthenticator\n )\n\n // ... other logic as needed\n }\n\nSimilar to `CreateEntry`, a `BiometricPromptData` instance is set to the\n`PublicKeyCredentialEntry` instance. If not explicitly set,\n`allowedAuthenticator` defaults to `BIOMETRIC_WEAK`. \n\n PublicKeyCredentialEntry(\n // other properties...\n\n biometricPromptData = BiometricPromptData(\n allowedAuthenticators = allowedAuthenticator\n )\n )\n\n| **Note:** The user is presented with a biometric authentication option if their device supports it and they have granted permission for its use. The code is similar to the previous example, with the addition of a [`cryptoObject`](/reference/androidx/biometric/BiometricPrompt.CryptoObject).\n\nHandle credential entry selection\n---------------------------------\n\nWhile handling the credential entry selection for [passkey creation](/identity/sign-in/credential-provider#handle-passkey-credential) or\n[passkey selection during sign in](/identity/sign-in/credential-provider#passkeys-implement), call the `PendingIntentHandler's\nretrieveProviderCreateCredentialRequest`, or\n`retrieveProviderGetCredentialRequest`, as appropriate. These return objects\nthat contain the metadata needed for the provider. For example, when handling\npasskey creation entry selection, update your code as shown: \n\n val createRequest = PendingIntentHandler.retrieveProviderCreateCredentialRequest(intent)\n if (createRequest == null) {\n Log.i(TAG, \"request is null\")\n setUpFailureResponseAndFinish(\"Unable to extract request from intent\")\n return\n }\n // Other logic...\n\n val biometricPromptResult = createRequest.biometricPromptResult\n\n // Add your logic based on what needs to be done\n // after getting biometrics\n\n if (createRequest.callingRequest is CreatePublicKeyCredentialRequest) {\n val publicKeyRequest: CreatePublicKeyCredentialRequest =\n createRequest.callingRequest as CreatePublicKeyCredentialRequest\n\n if (biometricPromptResult == null) {\n // Do your own authentication flow, if needed\n } else if (biometricPromptResult.isSuccessful) {\n createPasskey(\n publicKeyRequest.requestJson,\n createRequest.callingAppInfo,\n publicKeyRequest.clientDataHash,\n accountId\n )\n } else {\n val error = biometricPromptResult.authenticationError\n // Process the error\n }\n\n // Other logic...\n }\n\nThis example contains information about the biometric flow's success. It also\ncontains other information about the credential. If the flow fails, use the\nerror code under `biometricPromptResult.authenticationError` to make decisions.\nThe error codes returned as part of\n`biometricPromptResult.authenticationError.errorCode` are the same error codes\ndefined in the androidx.biometric library, such as\n[androidx.biometric.BiometricPrompt.NO_SPACE](/reference/androidx/biometric/BiometricPrompt#ERROR_NO_SPACE()),\n[androidx.biometric.BiometricPrompt.UNABLE_TO_PROCESS](/identity/sign-in/androidx.biometric.BiometricPrompt.NO_SPACE),\n[androidx.biometric.BiometricPrompt.ERROR_TIMEOUT](/reference/androidx/biometric/BiometricPrompt#ERROR_TIMEOUT()), and similar. The\n`authenticationError` will also contain an error message associated with the\n`errorCode` that can be displayed on a UI.\n\nSimilarly, extract metadata during the `retrieveProviderGetCredentialRequest`.\nCheck if your biometric flow is `null`. If yes, configure your own biometrics to\nauthenticate. This is similar to how the [get operation](/identity/sign-in/credential-provider#passkeys-implement) is instrumented: \n\n val getRequest =\n PendingIntentHandler.retrieveProviderGetCredentialRequest(intent)\n\n if (getRequest == null) {\n Log.i(TAG, \"request is null\")\n setUpFailureResponseAndFinish(\"Unable to extract request from intent\")\n return\n }\n\n // Other logic...\n\n val biometricPromptResult = getRequest.biometricPromptResult\n\n // Add your logic based on what needs to be done\n // after getting biometrics\n\n if (biometricPromptResult == null) {\n // Do your own authentication flow, if necessary\n } else if (biometricPromptResult.isSuccessful) {\n\n Log.i(TAG, \"The response from the biometricPromptResult was ${biometricPromptResult.authenticationResult?.authenticationType}\")\n\n validatePasskey(\n publicKeyRequest.requestJson,\n origin,\n packageName,\n uid,\n passkey.username,\n credId,\n privateKey\n )\n } else {\n val error = biometricPromptResult.authenticationError\n // Process the error\n }\n\n // Other logic..."]]