Java源码示例:org.keycloak.credential.CredentialModel
示例1
@Override
public void onEvent(Event event) {
if (!EventType.LOGIN.equals(event.getType())) {
return;
}
log.infof("onEvent: event=%s", event.getType());
UserProvider users = this.session.getProvider(UserProvider.class);
RealmModel realm = session.getContext().getRealm();
UserModel user = users.getUserById(event.getUserId(), realm);
if (userHasRole(realm, user, "admin")) {
return;
}
log.infof("onEvent: event=%s disable password credentials", event.getType());
UserCredentialManager credentialManager = session.userCredentialManager();
credentialManager.disableCredentialType(realm, user, CredentialModel.PASSWORD);
UserCache userCache = session.getProvider(UserCache.class);
userCache.evict(realm, user);
}
示例2
/**
* Create OTP credential either in userStorage or local storage (Keycloak DB)
*
* @return true if credential was successfully created either in the user storage or Keycloak DB. False if error happened (EG. during HOTP validation)
*/
public static boolean createOTPCredential(KeycloakSession session, RealmModel realm, UserModel user, String totpCode, OTPCredentialModel credentialModel) {
CredentialProvider otpCredentialProvider = session.getProvider(CredentialProvider.class, "keycloak-otp");
String totpSecret = credentialModel.getOTPSecretData().getValue();
UserCredentialModel otpUserCredential = new UserCredentialModel("", realm.getOTPPolicy().getType(), totpSecret);
boolean userStorageCreated = session.userCredentialManager().updateCredential(realm, user, otpUserCredential);
String credentialId = null;
if (userStorageCreated) {
logger.debugf("Created OTP credential for user '%s' in the user storage", user.getUsername());
} else {
CredentialModel createdCredential = otpCredentialProvider.createCredential(realm, user, credentialModel);
credentialId = createdCredential.getId();
}
//If the type is HOTP, call verify once to consume the OTP used for registration and increase the counter.
UserCredentialModel credential = new UserCredentialModel(credentialId, otpCredentialProvider.getType(), totpCode);
return session.userCredentialManager().isValid(realm, user, credential);
}
示例3
@Test
public void testCredentialModelOTP() {
CredentialModel otp = OTPCredentialModel.createTOTP("456123", 6, 30, "someAlg");
Assert.assertEquals("456123", otp.getValue());
Assert.assertEquals(6, otp.getDigits());
Assert.assertEquals(30, otp.getPeriod());
Assert.assertEquals("someAlg", otp.getAlgorithm());
// Change something and assert it is changed
otp.setValue("789789");
Assert.assertEquals("789789", otp.getValue());
// Test clone
OTPCredentialModel cloned = OTPCredentialModel.createFromCredentialModel(otp);
Assert.assertEquals("789789", cloned.getOTPSecretData().getValue());
Assert.assertEquals(6, cloned.getOTPCredentialData().getDigits());
Assert.assertEquals("someAlg", cloned.getOTPCredentialData().getAlgorithm());
}
示例4
@Test
public void testCredentialModelPassword() {
byte[] salt = { 1, 2, 3 };
CredentialModel password = PasswordCredentialModel.createFromValues("foo", salt, 1000, "pass");
Assert.assertEquals("pass", password.getValue());
Assert.assertTrue(Arrays.areEqual(salt, password.getSalt()));
Assert.assertEquals(1000, password.getHashIterations());
Assert.assertEquals("foo", password.getAlgorithm());
// Change something and assert it is changed
password.setValue("789789");
Assert.assertEquals("789789", password.getValue());
// Test clone
PasswordCredentialModel cloned = PasswordCredentialModel.createFromCredentialModel(password);
Assert.assertEquals("789789", cloned.getPasswordSecretData().getValue());
Assert.assertEquals(1000, cloned.getPasswordCredentialData().getHashIterations());
Assert.assertEquals(1000, cloned.getPasswordCredentialData().getHashIterations());
Assert.assertEquals("foo", cloned.getPasswordCredentialData().getAlgorithm());
}
示例5
@Override
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
if (!(input instanceof UserCredentialModel)) {
logger.debug("Expected instance of UserCredentialModel for CredentialInput");
return false;
}
if (!input.getType().equals(getType())) {
return false;
}
String challengeResponse = input.getChallengeResponse();
if (challengeResponse == null) {
return false;
}
CredentialModel credentialModel = getCredentialStore().getStoredCredentialById(realm, user, input.getCredentialId());
SecretQuestionCredentialModel sqcm = getCredentialFromModel(credentialModel);
return sqcm.getSecretQuestionSecretData().getAnswer().equals(challengeResponse);
}
示例6
public static SecretQuestionCredentialModel createFromCredentialModel(CredentialModel credentialModel){
try {
SecretQuestionCredentialData credentialData = JsonSerialization.readValue(credentialModel.getCredentialData(), SecretQuestionCredentialData.class);
SecretQuestionSecretData secretData = JsonSerialization.readValue(credentialModel.getSecretData(), SecretQuestionSecretData.class);
SecretQuestionCredentialModel secretQuestionCredentialModel = new SecretQuestionCredentialModel(credentialData, secretData);
secretQuestionCredentialModel.setUserLabel(credentialModel.getUserLabel());
secretQuestionCredentialModel.setCreatedDate(credentialModel.getCreatedDate());
secretQuestionCredentialModel.setType(TYPE);
secretQuestionCredentialModel.setId(credentialModel.getId());
secretQuestionCredentialModel.setSecretData(credentialModel.getSecretData());
secretQuestionCredentialModel.setCredentialData(credentialModel.getCredentialData());
return secretQuestionCredentialModel;
} catch (IOException e){
throw new RuntimeException(e);
}
}
示例7
@Test
@AuthServerContainerExclude(AuthServer.REMOTE)
public void createUserWithRawCredentials() {
UserRepresentation user = new UserRepresentation();
user.setUsername("user_rawpw");
user.setEmail("[email protected]");
CredentialRepresentation rawPassword = new CredentialRepresentation();
rawPassword.setValue("ABCD");
rawPassword.setType(CredentialRepresentation.PASSWORD);
user.setCredentials(Arrays.asList(rawPassword));
createUser(user);
CredentialModel credential = fetchCredentials("user_rawpw");
assertNotNull("Expecting credential", credential);
PasswordCredentialModel pcm = PasswordCredentialModel.createFromCredentialModel(credential);
assertEquals(PasswordPolicy.HASH_ALGORITHM_DEFAULT, pcm.getPasswordCredentialData().getAlgorithm());
assertEquals(PasswordPolicy.HASH_ITERATIONS_DEFAULT, pcm.getPasswordCredentialData().getHashIterations());
assertNotEquals("ABCD", pcm.getPasswordSecretData().getValue());
assertEquals(CredentialRepresentation.PASSWORD, credential.getType());
}
示例8
@GET
@Path("password")
@Produces(MediaType.APPLICATION_JSON)
public PasswordDetails passwordDetails() throws IOException {
auth.requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE);
PasswordCredentialProvider passwordProvider = (PasswordCredentialProvider) session.getProvider(CredentialProvider.class, PasswordCredentialProviderFactory.PROVIDER_ID);
CredentialModel password = passwordProvider.getPassword(realm, user);
PasswordDetails details = new PasswordDetails();
if (password != null) {
details.setRegistered(true);
Long createdDate = password.getCreatedDate();
if (createdDate != null) {
details.setLastUpdate(createdDate);
}
} else {
details.setRegistered(false);
}
return details;
}
示例9
public static FetchOnServerWrapper<CredentialModel> fetchCredentials(String username) {
return new FetchOnServerWrapper() {
@Override
public FetchOnServer getRunOnServer() {
return (FetchOnServer) session -> {
RealmModel realm = session.getContext().getRealm();
UserModel user = session.users().getUserByUsername(username, realm);
List<CredentialModel> storedCredentialsByType = session.userCredentialManager().getStoredCredentialsByType(realm, user, CredentialRepresentation.PASSWORD);
System.out.println(storedCredentialsByType.size());
return storedCredentialsByType.get(0);
};
}
@Override
public Class getResultClass() {
return CredentialModel.class;
}
};
}
示例10
CredentialModel toModel(CredentialEntity entity) {
CredentialModel model = new CredentialModel();
model.setId(entity.getId());
model.setType(entity.getType());
model.setCreatedDate(entity.getCreatedDate());
model.setUserLabel(entity.getUserLabel());
// Backwards compatibility - users from previous version still have "salt" in the DB filled.
// We migrate it to new secretData format on-the-fly
if (entity.getSalt() != null) {
String newSecretData = entity.getSecretData().replace("__SALT__", Base64.encodeBytes(entity.getSalt()));
entity.setSecretData(newSecretData);
entity.setSalt(null);
}
model.setSecretData(entity.getSecretData());
model.setCredentialData(entity.getCredentialData());
return model;
}
示例11
CredentialEntity createCredentialEntity(RealmModel realm, UserModel user, CredentialModel cred) {
CredentialEntity entity = new CredentialEntity();
String id = cred.getId() == null ? KeycloakModelUtils.generateId() : cred.getId();
entity.setId(id);
entity.setCreatedDate(cred.getCreatedDate());
entity.setUserLabel(cred.getUserLabel());
entity.setType(cred.getType());
entity.setSecretData(cred.getSecretData());
entity.setCredentialData(cred.getCredentialData());
UserEntity userRef = em.getReference(UserEntity.class, user.getId());
entity.setUser(userRef);
//add in linkedlist to last position
List<CredentialEntity> credentials = getStoredCredentialEntities(realm, user);
int priority = credentials.isEmpty() ? PRIORITY_DIFFERENCE : credentials.get(credentials.size() - 1).getPriority() + PRIORITY_DIFFERENCE;
entity.setPriority(priority);
em.persist(entity);
return entity;
}
示例12
@Override
public List<CredentialModel> getStoredCredentialsByType(RealmModel realm, UserModel user, String type) {
List<CredentialEntity> results;
UserEntity userEntity = userInEntityManagerContext(user.getId());
if (userEntity != null) {
// user already in persistence context, no need to execute a query
results = userEntity.getCredentials().stream().filter(it -> type.equals(it.getType()))
.sorted(Comparator.comparingInt(CredentialEntity::getPriority))
.collect(Collectors.toList());
List<CredentialModel> rtn = new LinkedList<>();
for (CredentialEntity entity : results) {
rtn.add(toModel(entity));
}
return rtn;
} else {
return credentialStore.getStoredCredentialsByType(realm, user, type);
}
}
示例13
@Override
public CredentialModel createCredential(RealmModel realm, String userId, CredentialModel cred) {
createIndex(realm, userId);
FederatedUserCredentialEntity entity = new FederatedUserCredentialEntity();
String id = cred.getId() == null ? KeycloakModelUtils.generateId() : cred.getId();
entity.setId(id);
entity.setCreatedDate(cred.getCreatedDate());
entity.setType(cred.getType());
entity.setCredentialData(cred.getCredentialData());
entity.setSecretData(cred.getSecretData());
entity.setUserLabel(cred.getUserLabel());
entity.setUserId(userId);
entity.setRealmId(realm.getId());
entity.setStorageProviderId(new StorageId(userId).getProviderId());
//add in linkedlist to last position
List<FederatedUserCredentialEntity> credentials = getStoredCredentialEntities(userId);
int priority = credentials.isEmpty() ? JpaUserCredentialStore.PRIORITY_DIFFERENCE : credentials.get(credentials.size() - 1).getPriority() + JpaUserCredentialStore.PRIORITY_DIFFERENCE;
entity.setPriority(priority);
em.persist(entity);
return toModel(entity);
}
示例14
protected CredentialModel toModel(FederatedUserCredentialEntity entity) {
CredentialModel model = new CredentialModel();
model.setId(entity.getId());
model.setType(entity.getType());
model.setCreatedDate(entity.getCreatedDate());
model.setUserLabel(entity.getUserLabel());
// Backwards compatibility - users from previous version still have "salt" in the DB filled.
// We migrate it to new secretData format on-the-fly
if (entity.getSalt() != null) {
String newSecretData = entity.getSecretData().replace("__SALT__", Base64.encodeBytes(entity.getSalt()));
entity.setSecretData(newSecretData);
entity.setSalt(null);
}
model.setSecretData(entity.getSecretData());
model.setCredentialData(entity.getCredentialData());
return model;
}
示例15
public TotpBean(KeycloakSession session, RealmModel realm, UserModel user, UriBuilder uriBuilder) {
this.uriBuilder = uriBuilder;
this.enabled = session.userCredentialManager().isConfiguredFor(realm, user, OTPCredentialModel.TYPE);
if (enabled) {
List<CredentialModel> otpCredentials = session.userCredentialManager().getStoredCredentialsByType(realm, user, OTPCredentialModel.TYPE);
if (otpCredentials.isEmpty()) {
// Credential is configured on userStorage side. Create the "fake" credential similar like we do for the new account console
CredentialRepresentation credential = createUserStorageCredentialRepresentation(OTPCredentialModel.TYPE);
this.otpCredentials = Collections.singletonList(RepresentationToModel.toModel(credential));
} else {
this.otpCredentials = otpCredentials;
}
} else {
this.otpCredentials = Collections.EMPTY_LIST;
}
this.realm = realm;
this.totpSecret = HmacOTP.generateSecret(20);
this.totpSecretEncoded = TotpUtils.encode(totpSecret);
this.totpSecretQrCode = TotpUtils.qrCode(totpSecret, realm, user);
}
示例16
public static OTPCredentialModel createFromCredentialModel(CredentialModel credentialModel) {
try {
OTPCredentialData credentialData = JsonSerialization.readValue(credentialModel.getCredentialData(), OTPCredentialData.class);
OTPSecretData secretData = JsonSerialization.readValue(credentialModel.getSecretData(), OTPSecretData.class);
OTPCredentialModel otpCredentialModel = new OTPCredentialModel(credentialData, secretData);
otpCredentialModel.setUserLabel(credentialModel.getUserLabel());
otpCredentialModel.setCreatedDate(credentialModel.getCreatedDate());
otpCredentialModel.setType(TYPE);
otpCredentialModel.setId(credentialModel.getId());
otpCredentialModel.setSecretData(credentialModel.getSecretData());
otpCredentialModel.setCredentialData(credentialModel.getCredentialData());
return otpCredentialModel;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
示例17
public static PasswordCredentialModel createFromCredentialModel(CredentialModel credentialModel) {
try {
PasswordCredentialData credentialData = JsonSerialization.readValue(credentialModel.getCredentialData(),
PasswordCredentialData.class);
PasswordSecretData secretData = JsonSerialization.readValue(credentialModel.getSecretData(), PasswordSecretData.class);
PasswordCredentialModel passwordCredentialModel = new PasswordCredentialModel(credentialData, secretData);
passwordCredentialModel.setCreatedDate(credentialModel.getCreatedDate());
passwordCredentialModel.setCredentialData(credentialModel.getCredentialData());
passwordCredentialModel.setId(credentialModel.getId());
passwordCredentialModel.setSecretData(credentialModel.getSecretData());
passwordCredentialModel.setType(credentialModel.getType());
passwordCredentialModel.setUserLabel(credentialModel.getUserLabel());
return passwordCredentialModel;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
示例18
public static WebAuthnCredentialModel createFromCredentialModel(CredentialModel credentialModel) {
try {
WebAuthnCredentialData credentialData = JsonSerialization.readValue(credentialModel.getCredentialData(), WebAuthnCredentialData.class);
WebAuthnSecretData secretData = JsonSerialization.readValue(credentialModel.getSecretData(), WebAuthnSecretData.class);
WebAuthnCredentialModel webAuthnCredentialModel = new WebAuthnCredentialModel(credentialModel.getType(), credentialData, secretData);
webAuthnCredentialModel.setUserLabel(credentialModel.getUserLabel());
webAuthnCredentialModel.setCreatedDate(credentialModel.getCreatedDate());
webAuthnCredentialModel.setType(credentialModel.getType());
webAuthnCredentialModel.setId(credentialModel.getId());
webAuthnCredentialModel.setSecretData(credentialModel.getSecretData());
webAuthnCredentialModel.setCredentialData(credentialModel.getCredentialData());
return webAuthnCredentialModel;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
示例19
@Override
public void evaluateTriggers(RequiredActionContext context) {
int daysToExpirePassword = context.getRealm().getPasswordPolicy().getDaysToExpirePassword();
if(daysToExpirePassword != -1) {
PasswordCredentialProvider passwordProvider = (PasswordCredentialProvider)context.getSession().getProvider(CredentialProvider.class, PasswordCredentialProviderFactory.PROVIDER_ID);
CredentialModel password = passwordProvider.getPassword(context.getRealm(), context.getUser());
if (password != null) {
if(password.getCreatedDate() == null) {
context.getUser().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
logger.debug("User is required to update password");
} else {
long timeElapsed = Time.toMillis(Time.currentTime()) - password.getCreatedDate();
long timeToExpire = TimeUnit.DAYS.toMillis(daysToExpirePassword);
if(timeElapsed > timeToExpire) {
context.getUser().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
logger.debug("User is required to update password");
}
}
}
}
}
示例20
/**
* Update a user label of specified credential of current user
*
* @param credentialId ID of the credential, which will be updated
* @param userLabel new user label as JSON string
*/
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Path("{credentialId}/label")
@NoCache
public void setLabel(final @PathParam("credentialId") String credentialId, String userLabel) {
auth.require(AccountRoles.MANAGE_ACCOUNT);
CredentialModel credential = session.userCredentialManager().getStoredCredentialById(realm, user, credentialId);
if (credential == null) {
throw new NotFoundException("Credential not found");
}
try {
String label = JsonSerialization.readValue(userLabel, String.class);
session.userCredentialManager().updateCredentialLabel(realm, user, credentialId, label);
} catch (IOException ioe) {
throw new ErrorResponseException(ErrorResponse.error(Messages.INVALID_REQUEST, Response.Status.BAD_REQUEST));
}
}
示例21
@Override
public void authenticate(AuthenticationFlowContext context) {
RealmModel realm = context.getRealm();
UserModel user = context.getUser();
Map<String, String> config = (context.getAuthenticatorConfig() == null ? Collections.emptyMap() : context.getAuthenticatorConfig().getConfig());
List<CredentialModel> passwords = context.getSession().userCredentialManager().getStoredCredentialsByType(realm, user, PasswordCredentialModel.TYPE);
if (!passwords.isEmpty()) {
CredentialModel passwordCredential = passwords.get(0);
Instant creationTime = Instant.ofEpochMilli(passwordCredential.getCreatedDate());
Duration minPasswordAge = Duration.parse(config.getOrDefault(MIN_PASSWORD_AGE_DURATION, "PT15M"));
if (creationTime.isAfter(Instant.now().minus(minPasswordAge))) {
log.warnf("Access denied because of min password age. realm=%s username=%s", realm.getName(), user.getUsername());
context.getEvent().user(user);
context.getEvent().error(Errors.NOT_ALLOWED);
context.forkWithErrorMessage(new FormMessage(Messages.NO_ACCESS));
return;
}
}
context.success();
}
示例22
private BetterCredentialRepresentation exportCredential(CredentialModel userCred) {
BetterCredentialRepresentation credRep = new BetterCredentialRepresentation();
credRep.setId(userCred.getId());
credRep.setType(userCred.getType());
credRep.setCreatedDate(userCred.getCreatedDate());
credRep.setCredentialData(userCred.getCredentialData());
credRep.setSecretData(userCred.getSecretData());
credRep.setUserLabel(userCred.getUserLabel());
return credRep;
}
示例23
public static CredentialRepresentation toRepresentation(CredentialModel cred) {
CredentialRepresentation rep = new CredentialRepresentation();
rep.setId(cred.getId());
rep.setType(cred.getType());
rep.setUserLabel(cred.getUserLabel());
rep.setCreatedDate(cred.getCreatedDate());
rep.setSecretData(cred.getSecretData());
rep.setCredentialData(cred.getCredentialData());
return rep;
}
示例24
@Test
public void testCredentialModelConfigMap() {
MultivaluedHashMap<String, String> map = new MultivaluedHashMap<>();
map.add("key1", "val11");
map.add("key1", "val12");
map.add("key2", "val21");
CredentialModel credential = new CredentialModel();
Assert.assertNull(credential.getConfig());
credential.setConfig(map);
MultivaluedHashMap<String, String> loadedMap = credential.getConfig();
Assert.assertEquals(map, loadedMap);
}
示例25
@Override
public CredentialModel createCredential(RealmModel realm, UserModel user, SecretQuestionCredentialModel credentialModel) {
if (credentialModel.getCreatedDate() == null) {
credentialModel.setCreatedDate(Time.currentTimeMillis());
}
return getCredentialStore().createCredential(realm, user, credentialModel);
}
示例26
@GET
@Path("credentials")
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public List<CredentialRepresentation> credentials(){
auth.users().requireManage(user);
List<CredentialModel> models = session.userCredentialManager().getStoredCredentials(realm, user);
models.forEach(c -> c.setSecretData(null));
return models.stream().map(ModelToRepresentation::toRepresentation).collect(Collectors.toList());
}
示例27
@Test
@AuthServerContainerExclude(AuthServer.REMOTE)
public void createUserWithHashedCredentials() {
UserRepresentation user = new UserRepresentation();
user.setUsername("user_creds");
user.setEmail("[email protected]");
PasswordCredentialModel pcm = PasswordCredentialModel.createFromValues("my-algorithm", "theSalt".getBytes(), 22, "ABC");
CredentialRepresentation hashedPassword = ModelToRepresentation.toRepresentation(pcm);
hashedPassword.setCreatedDate(1001L);
hashedPassword.setUserLabel("deviceX");
hashedPassword.setType(CredentialRepresentation.PASSWORD);
user.setCredentials(Arrays.asList(hashedPassword));
createUser(user);
CredentialModel credentialHashed = fetchCredentials("user_creds");
PasswordCredentialModel pcmh = PasswordCredentialModel.createFromCredentialModel(credentialHashed);
assertNotNull("Expecting credential", credentialHashed);
assertEquals("my-algorithm", pcmh.getPasswordCredentialData().getAlgorithm());
assertEquals(Long.valueOf(1001), credentialHashed.getCreatedDate());
assertEquals("deviceX", credentialHashed.getUserLabel());
assertEquals(22, pcmh.getPasswordCredentialData().getHashIterations());
assertEquals("ABC", pcmh.getPasswordSecretData().getValue());
assertEquals("theSalt", new String(pcmh.getPasswordSecretData().getSalt()));
assertEquals(CredentialRepresentation.PASSWORD, credentialHashed.getType());
}
示例28
private void assertOrder(List<CredentialModel> creds, String... expectedIds) {
Assert.assertEquals(expectedIds.length, creds.size());
if (creds.size() == 0) return;
for (int i=0 ; i<expectedIds.length ; i++) {
Assert.assertEquals(creds.get(i).getId(), expectedIds[i]);
}
}
示例29
private void assertNumberOfStoredCredentials(int expectedNumberOfStoredCredentials) {
Assume.assumeTrue("Works only on auth-server-undertow",
AuthServerTestEnricher.AUTH_SERVER_CONTAINER.equals(AuthServerTestEnricher.AUTH_SERVER_CONTAINER_DEFAULT));
final String uId = userId; // Needed for run-on-server
testingClient.server("test").run(session -> {
RealmModel realm = session.getContext().getRealm();
UserModel user = session.users().getUserById(uId, realm);
assertThat(user, Matchers.notNullValue());
List<CredentialModel> storedCredentials = session.userCredentialManager().getStoredCredentials(realm, user);
assertThat(storedCredentials, Matchers.hasSize(expectedNumberOfStoredCredentials));
});
}
示例30
@Test
public void testDisableCredentialsInUserStorage() {
String userId = addUserAndResetPassword("otp1", "pass");
getCleanup().addUserId(userId);
// Setup OTP for the user
setupOTPForUserWithRequiredAction(userId);
// Assert user has OTP in the userStorage
assertUserDontHaveDBCredentials();
assertUserHasOTPCredentialInUserStorage(true);
UserResource user = testRealmResource().users().get(userId);
// Disable OTP credential for the user through REST endpoint
UserRepresentation userRep = user.toRepresentation();
Assert.assertNames(userRep.getDisableableCredentialTypes(), CredentialModel.OTP);
user.disableCredentialType(Collections.singletonList(CredentialModel.OTP));
// User don't have OTP credential in userStorage anymore
assertUserDontHaveDBCredentials();
assertUserHasOTPCredentialInUserStorage(false);
// Assert user can login without OTP
loginSuccessAndLogout("otp1", "pass");
}