Merge "Changing flat request string to a set of element keys." into udc-dev

This commit is contained in:
Omer Ozer
2023-03-28 15:11:18 +00:00
committed by Android (Google) Code Review
9 changed files with 98 additions and 116 deletions

View File

@@ -13644,10 +13644,10 @@ package android.credentials {
}
public final class CredentialDescription implements android.os.Parcelable {
ctor public CredentialDescription(@NonNull String, @NonNull String, @NonNull java.util.List<android.service.credentials.CredentialEntry>);
ctor public CredentialDescription(@NonNull String, @NonNull java.util.Set<java.lang.String>, @NonNull java.util.List<android.service.credentials.CredentialEntry>);
method public int describeContents();
method @NonNull public java.util.List<android.service.credentials.CredentialEntry> getCredentialEntries();
method @NonNull public String getFlattenedRequestString();
method @NonNull public java.util.Set<java.lang.String> getSupportedElementKeys();
method @NonNull public String getType();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.credentials.CredentialDescription> CREATOR;
@@ -13674,7 +13674,7 @@ package android.credentials {
method public boolean isSystemProviderRequired();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.credentials.CredentialOption> CREATOR;
field public static final String FLATTENED_REQUEST = "android.credentials.GetCredentialOption.FLATTENED_REQUEST_STRING";
field public static final String SUPPORTED_ELEMENT_KEYS = "android.credentials.GetCredentialOption.SUPPORTED_ELEMENT_KEYS";
}
public static final class CredentialOption.Builder {

View File

@@ -25,8 +25,10 @@ import com.android.internal.util.AnnotationValidations;
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* Represents the type and contained data fields of a {@link Credential}.
@@ -42,10 +44,10 @@ public final class CredentialDescription implements Parcelable {
private final String mType;
/**
* Flattened semicolon separated keys of JSON values to match with requests.
* Keys of elements to match with Credential requests.
*/
@NonNull
private final String mFlattenedRequestString;
private final Set<String> mSupportedElementKeys;
/**
* The credential entries to be used in the UI.
@@ -57,8 +59,7 @@ public final class CredentialDescription implements Parcelable {
* Constructs a {@link CredentialDescription}.
*
* @param type the type of the credential returned.
* @param flattenedRequestString flattened semicolon separated keys of JSON values
* to match with requests.
* @param supportedElementKeys Keys of elements to match with Credential requests.
* @param credentialEntries a list of {@link CredentialEntry}s that are to be shown on the
* account selector if a credential matches with this description.
* Each entry contains information to be displayed within an
@@ -68,10 +69,10 @@ public final class CredentialDescription implements Parcelable {
* @throws IllegalArgumentException If type is empty.
*/
public CredentialDescription(@NonNull String type,
@NonNull String flattenedRequestString,
@NonNull Set<String> supportedElementKeys,
@NonNull List<CredentialEntry> credentialEntries) {
mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
mFlattenedRequestString = Preconditions.checkStringNotEmpty(flattenedRequestString);
mSupportedElementKeys = Objects.requireNonNull(supportedElementKeys);
mCredentialEntries = Objects.requireNonNull(credentialEntries);
Preconditions.checkArgument(credentialEntries.size()
<= MAX_ALLOWED_ENTRIES_PER_DESCRIPTION,
@@ -82,15 +83,15 @@ public final class CredentialDescription implements Parcelable {
private CredentialDescription(@NonNull Parcel in) {
String type = in.readString8();
String flattenedRequestString = in.readString();
List<String> descriptions = in.createStringArrayList();
List<CredentialEntry> entries = new ArrayList<>();
in.readTypedList(entries, CredentialEntry.CREATOR);
mType = type;
AnnotationValidations.validate(android.annotation.NonNull.class, null, mType);
mFlattenedRequestString = flattenedRequestString;
mSupportedElementKeys = new HashSet<>(descriptions);
AnnotationValidations.validate(android.annotation.NonNull.class, null,
mFlattenedRequestString);
mSupportedElementKeys);
mCredentialEntries = entries;
AnnotationValidations.validate(android.annotation.NonNull.class, null,
mCredentialEntries);
@@ -125,7 +126,7 @@ public final class CredentialDescription implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString8(mType);
dest.writeString(mFlattenedRequestString);
dest.writeStringList(mSupportedElementKeys.stream().toList());
dest.writeTypedList(mCredentialEntries, flags);
}
@@ -141,8 +142,8 @@ public final class CredentialDescription implements Parcelable {
* Returns the flattened JSON string that will be matched with requests.
*/
@NonNull
public String getFlattenedRequestString() {
return mFlattenedRequestString;
public Set<String> getSupportedElementKeys() {
return new HashSet<>(mSupportedElementKeys);
}
/**
@@ -155,18 +156,18 @@ public final class CredentialDescription implements Parcelable {
/**
* {@link CredentialDescription#mType} and
* {@link CredentialDescription#mFlattenedRequestString} are enough for hashing. Constructor
* {@link CredentialDescription#mSupportedElementKeys} are enough for hashing. Constructor
* enforces {@link CredentialEntry} to have the same type and
* {@link android.app.slice.Slice} contained by the entry can not be hashed.
*/
@Override
public int hashCode() {
return Objects.hash(mType, mFlattenedRequestString);
return Objects.hash(mType, mSupportedElementKeys);
}
/**
* {@link CredentialDescription#mType} and
* {@link CredentialDescription#mFlattenedRequestString} are enough for equality check.
* {@link CredentialDescription#mSupportedElementKeys} are enough for equality check.
*/
@Override
public boolean equals(Object obj) {
@@ -175,6 +176,6 @@ public final class CredentialDescription implements Parcelable {
}
CredentialDescription other = (CredentialDescription) obj;
return mType.equals(other.mType)
&& mFlattenedRequestString.equals(other.mFlattenedRequestString);
&& mSupportedElementKeys.equals(other.mSupportedElementKeys);
}
}

View File

@@ -43,12 +43,12 @@ import java.util.Set;
public final class CredentialOption implements Parcelable {
/**
* Bundle key to the flattened version of the JSON request string. Framework will use this key
* Bundle key to the list of elements keys supported/requested. Framework will use this key
* to determine which types of Credentials will utilize Credential Registry when filtering
* Credential Providers to ping.
*/
public static final String FLATTENED_REQUEST = "android.credentials"
+ ".GetCredentialOption.FLATTENED_REQUEST_STRING";
public static final String SUPPORTED_ELEMENT_KEYS = "android.credentials"
+ ".GetCredentialOption.SUPPORTED_ELEMENT_KEYS";
/**
* The requested credential type.

View File

@@ -49,6 +49,7 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -126,11 +127,11 @@ public class CredentialManagerTest {
null, List.of(Slice.HINT_TITLE)).build();
mRegisterRequest = new RegisterCredentialDescriptionRequest(
new CredentialDescription(Credential.TYPE_PASSWORD_CREDENTIAL,
"{ \"foo\": \"bar\" }",
new HashSet<>(List.of("{ \"foo\": \"bar\" }")),
List.of(new CredentialEntry(Credential.TYPE_PASSWORD_CREDENTIAL, slice))));
mUnregisterRequest = new UnregisterCredentialDescriptionRequest(
new CredentialDescription(Credential.TYPE_PASSWORD_CREDENTIAL,
"{ \"foo\": \"bar\" }",
new HashSet<>(List.of("{ \"foo\": \"bar\" }")),
List.of(new CredentialEntry(Credential.TYPE_PASSWORD_CREDENTIAL, slice))));
final Context context = InstrumentationRegistry.getInstrumentation().getContext();

View File

@@ -25,19 +25,16 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
/** Contains information on what CredentialProvider has what provisioned Credential. */
public class CredentialDescriptionRegistry {
private static final String FLAT_STRING_SPLIT_REGEX = ";";
private static final int MAX_ALLOWED_CREDENTIAL_DESCRIPTIONS = 128;
private static final int MAX_ALLOWED_ENTRIES_PER_PROVIDER = 16;
@GuardedBy("sLock")
@@ -53,15 +50,15 @@ public class CredentialDescriptionRegistry {
/** Represents the results of a given query into the registry. */
public static final class FilterResult {
final String mPackageName;
final String mFlattenedRequest;
final Set<String> mElementKeys;
final List<CredentialEntry> mCredentialEntries;
@VisibleForTesting
FilterResult(String packageName,
String flattenedRequest,
Set<String> elementKeys,
List<CredentialEntry> credentialEntries) {
mPackageName = packageName;
mFlattenedRequest = flattenedRequest;
mElementKeys = elementKeys;
mCredentialEntries = credentialEntries;
}
}
@@ -166,18 +163,17 @@ public class CredentialDescriptionRegistry {
/** Returns package names and entries of a CredentialProviders that can satisfy a given
* {@link CredentialDescription}. */
public Set<FilterResult> getFilteredResultForProvider(String packageName,
String flatRequestString) {
Set<String> requestedKeyElements) {
Set<FilterResult> result = new HashSet<>();
if (!mCredentialDescriptions.containsKey(packageName)) {
return result;
}
Set<CredentialDescription> currentSet = mCredentialDescriptions.get(packageName);
Set<String> unflattenedRequestString = flatStringToSet(flatRequestString);
for (CredentialDescription containedDescription: currentSet) {
if (checkForMatch(flatStringToSet(containedDescription.getFlattenedRequestString()),
unflattenedRequestString)) {
if (checkForMatch(containedDescription.getSupportedElementKeys(),
requestedKeyElements)) {
result.add(new FilterResult(packageName,
containedDescription.getFlattenedRequestString(), containedDescription
containedDescription.getSupportedElementKeys(), containedDescription
.getCredentialEntries()));
}
}
@@ -186,18 +182,15 @@ public class CredentialDescriptionRegistry {
/** Returns package names of CredentialProviders that can satisfy a given
* {@link CredentialDescription}. */
public Set<FilterResult> getMatchingProviders(Set<String> flatRequestStrings) {
public Set<FilterResult> getMatchingProviders(Set<Set<String>> supportedElementKeys) {
Set<FilterResult> result = new HashSet<>();
Set<Set<String>> unflattenedRequestStrings = flatRequestStrings.stream().map(
CredentialDescriptionRegistry::flatStringToSet).collect(Collectors.toSet());
for (String packageName: mCredentialDescriptions.keySet()) {
Set<CredentialDescription> currentSet = mCredentialDescriptions.get(packageName);
for (CredentialDescription containedDescription : currentSet) {
if (canProviderSatisfyAny(flatStringToSet(containedDescription
.getFlattenedRequestString()),
unflattenedRequestStrings)) {
if (canProviderSatisfyAny(containedDescription.getSupportedElementKeys(),
supportedElementKeys)) {
result.add(new FilterResult(packageName,
containedDescription.getFlattenedRequestString(), containedDescription
containedDescription.getSupportedElementKeys(), containedDescription
.getCredentialEntries()));
}
}
@@ -211,24 +204,19 @@ public class CredentialDescriptionRegistry {
}
}
private static boolean canProviderSatisfyAny(Set<String> registeredUnflattenedStrings,
Set<Set<String>> requestedUnflattenedStrings) {
for (Set<String> requestedUnflattenedString : requestedUnflattenedStrings) {
if (registeredUnflattenedStrings.containsAll(requestedUnflattenedString)) {
private static boolean canProviderSatisfyAny(Set<String> registeredElementKeys,
Set<Set<String>> requestedElementKeys) {
for (Set<String> requestedUnflattenedString : requestedElementKeys) {
if (registeredElementKeys.containsAll(requestedUnflattenedString)) {
return true;
}
}
return false;
}
static boolean checkForMatch(Set<String> registeredUnflattenedStrings,
Set<String> requestedUnflattenedString) {
return registeredUnflattenedStrings.containsAll(requestedUnflattenedString);
}
static Set<String> flatStringToSet(String flatString) {
return new HashSet<>(Arrays
.asList(flatString.split(FLAT_STRING_SPLIT_REGEX)));
static boolean checkForMatch(Set<String> registeredElementKeys,
Set<String> requestedElementKeys) {
return registeredElementKeys.containsAll(requestedElementKeys);
}
}

View File

@@ -339,13 +339,14 @@ public final class CredentialManagerService
CredentialDescriptionRegistry.forUser(UserHandle.getCallingUserId());
// All requested credential descriptions based on the given request.
Set<String> requestedCredentialDescriptions =
Set<Set<String>> requestedCredentialDescriptions =
options.stream()
.map(
getCredentialOption ->
getCredentialOption
new HashSet<>(getCredentialOption
.getCredentialRetrievalData()
.getString(CredentialOption.FLATTENED_REQUEST))
.getStringArrayList(
CredentialOption.SUPPORTED_ELEMENT_KEYS)))
.collect(Collectors.toSet());
// All requested credential descriptions based on the given request.
@@ -356,15 +357,13 @@ public final class CredentialManagerService
new HashSet<>();
for (CredentialDescriptionRegistry.FilterResult filterResult : filterResults) {
Set<String> registeredUnflattenedStrings = CredentialDescriptionRegistry
.flatStringToSet(filterResult.mFlattenedRequest);
for (CredentialOption credentialOption : options) {
Set<String> requestedUnflattenedStrings = CredentialDescriptionRegistry
.flatStringToSet(credentialOption
Set<String> requestedElementKeys = new HashSet<>(
credentialOption
.getCredentialRetrievalData()
.getString(CredentialOption.FLATTENED_REQUEST));
if (CredentialDescriptionRegistry.checkForMatch(registeredUnflattenedStrings,
requestedUnflattenedStrings)) {
.getStringArrayList(CredentialOption.SUPPORTED_ELEMENT_KEYS));
if (CredentialDescriptionRegistry.checkForMatch(filterResult.mElementKeys,
requestedElementKeys)) {
result.add(new Pair<>(credentialOption, filterResult));
}
}
@@ -511,28 +510,20 @@ public final class CredentialManagerService
if (isCredentialDescriptionApiEnabled()) {
List<CredentialOption> optionsThatRequireActiveCredentials =
request.getCredentialOptions().stream()
.filter(
getCredentialOption ->
!TextUtils.isEmpty(
getCredentialOption
.getCredentialRetrievalData()
.getString(
CredentialOption
.FLATTENED_REQUEST,
null)))
.filter(credentialOption -> credentialOption
.getCredentialRetrievalData()
.getStringArrayList(
CredentialOption
.SUPPORTED_ELEMENT_KEYS) != null)
.toList();
List<CredentialOption> optionsThatDoNotRequireActiveCredentials =
request.getCredentialOptions().stream()
.filter(
getCredentialOption ->
TextUtils.isEmpty(
getCredentialOption
.getCredentialRetrievalData()
.getString(
CredentialOption
.FLATTENED_REQUEST,
null)))
.filter(credentialOption -> credentialOption
.getCredentialRetrievalData()
.getStringArrayList(
CredentialOption
.SUPPORTED_ELEMENT_KEYS) == null)
.toList();
List<ProviderSession> sessionsWithoutRemoteService =
@@ -590,28 +581,20 @@ public final class CredentialManagerService
if (isCredentialDescriptionApiEnabled()) {
List<CredentialOption> optionsThatRequireActiveCredentials =
request.getCredentialOptions().stream()
.filter(
getCredentialOption ->
!TextUtils.isEmpty(
getCredentialOption
.getCredentialRetrievalData()
.getString(
CredentialOption
.FLATTENED_REQUEST,
null)))
.filter(credentialOption -> credentialOption
.getCredentialRetrievalData()
.getStringArrayList(
CredentialOption
.SUPPORTED_ELEMENT_KEYS) != null)
.toList();
List<CredentialOption> optionsThatDoNotRequireActiveCredentials =
request.getCredentialOptions().stream()
.filter(
getCredentialOption ->
TextUtils.isEmpty(
getCredentialOption
.getCredentialRetrievalData()
.getString(
CredentialOption
.FLATTENED_REQUEST,
null)))
.filter(credentialOption -> credentialOption
.getCredentialRetrievalData()
.getStringArrayList(
CredentialOption
.SUPPORTED_ELEMENT_KEYS) == null)
.toList();
List<ProviderSession> sessionsWithoutRemoteService =

View File

@@ -38,6 +38,7 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -103,7 +104,7 @@ public class ProviderRegistryGetSession extends ProviderSession<CredentialOption
@NonNull
private final String mCredentialProviderPackageName;
@NonNull
private final String mFlattenedRequestOptionString;
private final Set<String> mElementKeys;
@VisibleForTesting
List<CredentialEntry> mCredentialEntries;
@@ -119,9 +120,9 @@ public class ProviderRegistryGetSession extends ProviderSession<CredentialOption
mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(userId);
mCallingAppInfo = callingAppInfo;
mCredentialProviderPackageName = servicePackageName;
mFlattenedRequestOptionString = requestOption
mElementKeys = new HashSet<>(requestOption
.getCredentialRetrievalData()
.getString(CredentialOption.FLATTENED_REQUEST);
.getStringArrayList(CredentialOption.SUPPORTED_ELEMENT_KEYS));
}
protected ProviderRegistryGetSession(@NonNull Context context,
@@ -136,9 +137,9 @@ public class ProviderRegistryGetSession extends ProviderSession<CredentialOption
mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(userId);
mCallingAppInfo = callingAppInfo;
mCredentialProviderPackageName = servicePackageName;
mFlattenedRequestOptionString = requestOption
mElementKeys = new HashSet<>(requestOption
.getCredentialRetrievalData()
.getString(CredentialOption.FLATTENED_REQUEST);
.getStringArrayList(CredentialOption.SUPPORTED_ELEMENT_KEYS));
}
private List<Entry> prepareUiCredentialEntries(
@@ -257,7 +258,7 @@ public class ProviderRegistryGetSession extends ProviderSession<CredentialOption
protected void invokeSession() {
mProviderResponse = mCredentialDescriptionRegistry
.getFilteredResultForProvider(mCredentialProviderPackageName,
mFlattenedRequestOptionString);
mElementKeys);
mCredentialEntries = mProviderResponse.stream().flatMap(
(Function<CredentialDescriptionRegistry.FilterResult,
Stream<CredentialEntry>>) filterResult

View File

@@ -33,6 +33,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -52,10 +53,12 @@ public class CredentialDescriptionRegistryTest {
private static final String CALLING_PACKAGE_NAME_2 = "com.credman.app2";
private static final String MDOC_CREDENTIAL_TYPE = "MDOC";
private static final String PASSKEY_CREDENTIAL_TYPE = "PASSKEY";
private static final String FLATTENED_REGISTRY =
"FLATTENED_REQ;FLATTENED_REQ123;FLATTENED_REQa";
private static final String FLATTENED_REGISTRY_2 = "FLATTENED_REQ_2";
private static final String FLATTENED_REQUEST = "FLATTENED_REQ;FLATTENED_REQ123";
private static final HashSet<String> FLATTENED_REGISTRY = new HashSet<>(List.of(
"FLATTENED_REQ", "FLATTENED_REQ123", "FLATTENED_REQa"));
private static final HashSet<String> FLATTENED_REGISTRY_2 =
new HashSet<>(List.of("FLATTENED_REQ_2"));
private static final HashSet<String> FLATTENED_REQUEST =
new HashSet<>(List.of("FLATTENED_REQ;FLATTENED_REQ123"));
private CredentialDescriptionRegistry mCredentialDescriptionRegistry;
private CredentialEntry mEntry;

View File

@@ -18,6 +18,7 @@ package com.android.server.credentials;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -59,6 +60,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -74,7 +76,8 @@ public class ProviderRegistryGetSessionTest {
private static final String CALLING_PACKAGE_NAME = "com.credman.app";
private static final int USER_ID_1 = 1;
private static final String FLATTENED_REQUEST = "FLATTENED_REQ";
private static final ArrayList<String> FLATTENED_REQUEST =
new ArrayList<>(List.of("FLATTENED_REQ"));
private static final String CP_SERVICE_NAME = "CredentialProvider";
private static final ComponentName CREDENTIAL_PROVIDER_COMPONENT =
new ComponentName(CALLING_PACKAGE_NAME, CP_SERVICE_NAME);
@@ -102,7 +105,8 @@ public class ProviderRegistryGetSessionTest {
MockitoAnnotations.initMocks(this);
final Context context = ApplicationProvider.getApplicationContext();
mRetrievalData = new Bundle();
mRetrievalData.putString(CredentialOption.FLATTENED_REQUEST, FLATTENED_REQUEST);
mRetrievalData.putStringArrayList(CredentialOption.SUPPORTED_ELEMENT_KEYS,
FLATTENED_REQUEST);
mCallingAppInfo = createCallingAppInfo();
mGetCredentialOption = new CredentialOption(CREDENTIAL_TYPE, mRetrievalData,
new Bundle(), false);
@@ -114,10 +118,10 @@ public class ProviderRegistryGetSessionTest {
when(mEntry.getSlice()).thenReturn(mSlice);
when(mEntry2.getSlice()).thenReturn(mSlice2);
mResult = new CredentialDescriptionRegistry.FilterResult(CALLING_PACKAGE_NAME,
FLATTENED_REQUEST,
new HashSet<>(FLATTENED_REQUEST),
List.of(mEntry, mEntry2));
mResponse.add(mResult);
when(mCredentialDescriptionRegistry.getFilteredResultForProvider(anyString(), anyString()))
when(mCredentialDescriptionRegistry.getFilteredResultForProvider(anyString(), anySet()))
.thenReturn(mResponse);
mProviderRegistryGetSession = ProviderRegistryGetSession
.createNewSession(context, USER_ID_1, mGetRequestSession,
@@ -129,7 +133,8 @@ public class ProviderRegistryGetSessionTest {
@Test
public void testInvokeSession_existingProvider_setsResults() {
final ArgumentCaptor<String> packageNameCaptor = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> flattenedRequestCaptor = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<Set<String>> flattenedRequestCaptor =
ArgumentCaptor.forClass(Set.class);
final ArgumentCaptor<ProviderSession.Status> statusCaptor =
ArgumentCaptor.forClass(ProviderSession.Status.class);
final ArgumentCaptor<ComponentName> cpComponentNameCaptor =
@@ -141,7 +146,7 @@ public class ProviderRegistryGetSessionTest {
packageNameCaptor.capture(),
flattenedRequestCaptor.capture());
assertThat(packageNameCaptor.getValue()).isEqualTo(CALLING_PACKAGE_NAME);
assertThat(flattenedRequestCaptor.getValue()).isEqualTo(FLATTENED_REQUEST);
assertThat(flattenedRequestCaptor.getValue()).containsExactly(FLATTENED_REQUEST);
verify(mGetRequestSession).onProviderStatusChanged(statusCaptor.capture(),
cpComponentNameCaptor.capture());
assertThat(statusCaptor.getValue()).isEqualTo(ProviderSession.Status.CREDENTIALS_RECEIVED);