use of org.keycloak.models.utils.TimeBasedOTP in project keycloak by keycloak.
the class TotpTest method testTotp.
@Test
public void testTotp() {
TimeBasedOTP totp = new TimeBasedOTP("HmacSHA1", 8, 30, 1);
String secret = "dSdmuHLQhkm54oIm0A0S";
String otp = totp.generateTOTP(secret);
Assert.assertTrue(totp.validateTOTP(otp, secret.getBytes(StandardCharsets.UTF_8)));
}
use of org.keycloak.models.utils.TimeBasedOTP in project keycloak by keycloak.
the class BackwardsCompatibilityUserStorage method isValid.
@Override
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
MyUser myUser = users.get(translateUserName(user.getUsername()));
if (myUser == null)
return false;
if (input.getType().equals(UserCredentialModel.PASSWORD)) {
if (!(input instanceof PasswordUserCredentialModel))
return false;
CredentialModel hashedPassword = myUser.hashedPassword;
if (hashedPassword == null) {
log.warnf("Password not set for user %s", user.getUsername());
return false;
}
PasswordUserCredentialModel userCredentialModel = (PasswordUserCredentialModel) input;
// Those are not supposed to be set when calling this method in Keycloak 4.8.3 for password credential
assertNull(userCredentialModel.getDevice());
assertNull(userCredentialModel.getAlgorithm());
PasswordPolicy policy = session.getContext().getRealm().getPasswordPolicy();
PasswordHashProvider hashProvider = getHashProvider(policy);
String rawPassword = userCredentialModel.getValue();
// Compatibility with 4.8.3 - using "legacy" signature of this method
return hashProvider.verify(rawPassword, hashedPassword);
} else if (isOTPType(input.getType())) {
UserCredentialModel otpCredential = (UserCredentialModel) input;
// Special hardcoded OTP, which is always considered valid
if ("123456".equals(otpCredential.getValue())) {
return true;
}
CredentialModel storedOTPCredential = myUser.otp;
if (storedOTPCredential == null) {
log.warnf("Not found credential for the user %s", user.getUsername());
return false;
}
TimeBasedOTP validator = new TimeBasedOTP(storedOTPCredential.getAlgorithm(), storedOTPCredential.getDigits(), storedOTPCredential.getPeriod(), realm.getOTPPolicy().getLookAheadWindow());
return validator.validateTOTP(otpCredential.getValue(), storedOTPCredential.getValue().getBytes());
} else {
log.infof("Not supported to validate credential of type '%s' for user '%s'", input.getType(), user.getUsername());
return false;
}
}
use of org.keycloak.models.utils.TimeBasedOTP in project keycloak by keycloak.
the class RequiredActionPriorityTest method setupTotpAfterUpdatePassword.
@Test
public void setupTotpAfterUpdatePassword() {
String testUserId = ApiUtil.findUserByUsername(testRealm(), "test-user@localhost").getId();
setRequiredActionEnabled("test", testUserId, RequiredAction.CONFIGURE_TOTP.name(), true);
setRequiredActionEnabled("test", testUserId, RequiredAction.UPDATE_PASSWORD.name(), true);
setRequiredActionEnabled("test", testUserId, TermsAndConditions.PROVIDER_ID, false);
setRequiredActionEnabled("test", testUserId, RequiredAction.UPDATE_PROFILE.name(), false);
// make UPDATE_PASSWORD on top
testRealm().flows().raiseRequiredActionPriority(UserModel.RequiredAction.UPDATE_PASSWORD.name());
testRealm().flows().raiseRequiredActionPriority(UserModel.RequiredAction.UPDATE_PASSWORD.name());
// Login
loginPage.open();
loginPage.login("test-user@localhost", "password");
// change password
changePasswordPage.assertCurrent();
changePasswordPage.changePassword("new-password", "new-password");
events.expectRequiredAction(EventType.UPDATE_PASSWORD).assertEvent();
// CONFIGURE_TOTP
totpPage.assertCurrent();
totpPage.clickManual();
String pageSource = driver.getPageSource();
assertThat(pageSource, not(containsString("Unable to scan?")));
assertThat(pageSource, containsString("Scan barcode?"));
TimeBasedOTP totp = new TimeBasedOTP();
totpPage.configure(totp.generateTOTP(totpPage.getTotpSecret()), "userLabel");
events.expectRequiredAction(EventType.UPDATE_TOTP).assertEvent();
// Logined
appPage.assertCurrent();
assertThat(appPage.getRequestType(), is(RequestType.AUTH_RESPONSE));
events.expectLogin().assertEvent();
}
use of org.keycloak.models.utils.TimeBasedOTP in project keycloak by keycloak.
the class AbstractMigrationTest method testCredentialsMigratedToNewFormat.
protected void testCredentialsMigratedToNewFormat() {
log.info("testing user's credentials migrated to new format with secretData and credentialData");
// Try to login with password+otp after the migration
try {
oauth.realm(MIGRATION);
oauth.clientId("migration-test-client");
TimeBasedOTP otpGenerator = new TimeBasedOTP("HmacSHA1", 8, 40, 1);
String otp = otpGenerator.generateTOTP("dSdmuHLQhkm54oIm0A0S");
// Try invalid password first
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("secret", "migration-test-user", "password", otp);
Assert.assertNull(response.getAccessToken());
Assert.assertNotNull(response.getError());
// Try invalid OTP then
response = oauth.doGrantAccessTokenRequest("secret", "migration-test-user", "password2", "invalid");
Assert.assertNull(response.getAccessToken());
Assert.assertNotNull(response.getError());
// Try successful login now
response = oauth.doGrantAccessTokenRequest("secret", "migration-test-user", "password2", otp);
Assert.assertNull(response.getError());
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
assertEquals("migration-test-user", accessToken.getPreferredUsername());
} catch (Exception e) {
throw new AssertionError("Failed to login with user 'migration-test-user' after migration", e);
}
}
use of org.keycloak.models.utils.TimeBasedOTP in project keycloak by keycloak.
the class SigningInTest method beforeSigningInTest.
@Before
public void beforeSigningInTest() {
passwordCredentialType = signingInPage.getCredentialType(PasswordCredentialModel.TYPE);
otpCredentialType = signingInPage.getCredentialType(OTPCredentialModel.TYPE);
RealmRepresentation realm = testRealmResource().toRepresentation();
otpGenerator = new TimeBasedOTP(realm.getOtpPolicyAlgorithm(), realm.getOtpPolicyDigits(), realm.getOtpPolicyPeriod(), 0);
}
Aggregations