From f245b6703690260774cd82ded1247381afb2d0aa Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Fri, 21 Aug 2015 17:53:26 -0400 Subject: [PATCH] totp refactor --- .../theme/base/login/login-config-totp.ftl | 2 +- .../requiredactions/UpdateTotp.java | 50 ++++++++++++++++-- .../resources/LoginActionsService.java | 52 ------------------- 3 files changed, 46 insertions(+), 58 deletions(-) diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-config-totp.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-config-totp.ftl index f1effe7bcb..fc264f9ac5 100755 --- a/forms/common-themes/src/main/resources/theme/base/login/login-config-totp.ftl +++ b/forms/common-themes/src/main/resources/theme/base/login/login-config-totp.ftl @@ -5,7 +5,7 @@ <#elseif section = "header"> ${msg("loginTotpTitle")} <#elseif section = "form"> -
+
diff --git a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java index 61b035ab77..82adf9b7c8 100755 --- a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java +++ b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java @@ -5,13 +5,23 @@ import org.keycloak.Config; import org.keycloak.authentication.RequiredActionContext; import org.keycloak.authentication.RequiredActionFactory; import org.keycloak.authentication.RequiredActionProvider; +import org.keycloak.events.EventBuilder; +import org.keycloak.events.EventType; import org.keycloak.login.LoginFormsProvider; +import org.keycloak.models.ClientSessionModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.RequiredCredentialModel; +import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; +import org.keycloak.models.UserSessionModel; +import org.keycloak.models.utils.CredentialValidation; import org.keycloak.representations.idm.CredentialRepresentation; +import org.keycloak.services.managers.ClientSessionCode; +import org.keycloak.services.messages.Messages; +import org.keycloak.services.validation.Validation; +import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; /** @@ -26,16 +36,46 @@ public class UpdateTotp implements RequiredActionProvider, RequiredActionFactory @Override public void requiredActionChallenge(RequiredActionContext context) { - LoginFormsProvider loginFormsProvider = context.getSession().getProvider(LoginFormsProvider.class) - .setClientSessionCode(context.generateAccessCode(UserModel.RequiredAction.CONFIGURE_TOTP.name())) - .setUser(context.getUser()); - Response challenge = loginFormsProvider.createResponse(UserModel.RequiredAction.CONFIGURE_TOTP); + Response challenge = context.form().createResponse(UserModel.RequiredAction.CONFIGURE_TOTP); context.challenge(challenge); } @Override public void processAction(RequiredActionContext context) { - context.failure(); + EventBuilder event = context.getEvent(); + event.event(EventType.UPDATE_TOTP); + MultivaluedMap formData = context.getHttpRequest().getDecodedFormParameters(); + String totp = formData.getFirst("totp"); + String totpSecret = formData.getFirst("totpSecret"); + + if (Validation.isBlank(totp)) { + Response challenge = context.form() + .setError(Messages.MISSING_TOTP) + .createResponse(UserModel.RequiredAction.CONFIGURE_TOTP); + context.challenge(challenge); + return; + } else if (!CredentialValidation.validOTP(context.getRealm(), totp, totpSecret)) { + Response challenge = context.form() + .setError(Messages.INVALID_TOTP) + .createResponse(UserModel.RequiredAction.CONFIGURE_TOTP); + context.challenge(challenge); + return; + } + + UserCredentialModel credentials = new UserCredentialModel(); + credentials.setType(context.getRealm().getOTPPolicy().getType()); + credentials.setValue(totpSecret); + context.getSession().users().updateCredential(context.getRealm(), context.getUser(), credentials); + + + // if type is HOTP, to update counter we execute validation based on supplied token + UserCredentialModel cred = new UserCredentialModel(); + cred.setType(context.getRealm().getOTPPolicy().getType()); + cred.setValue(totp); + context.getSession().users().validCredentials(context.getRealm(), context.getUser(), cred); + + context.getUser().setOtpEnabled(true); + context.success(); } diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java index eea24990ea..edd9e6a037 100755 --- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java +++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java @@ -576,58 +576,6 @@ public class LoginActionsService { return AuthenticationManager.nextActionAfterAuthentication(session, userSession, clientSession, clientConnection, request, uriInfo, event); } - @Path("totp") - @POST - @Consumes(MediaType.APPLICATION_FORM_URLENCODED) - public Response updateTotp(@QueryParam("code") String code, - final MultivaluedMap formData) { - event.event(EventType.UPDATE_TOTP); - Checks checks = new Checks(); - if (!checks.verifyCode(code, ClientSessionModel.Action.CONFIGURE_TOTP.name())) { - return checks.response; - } - ClientSessionCode accessCode = checks.clientCode; - ClientSessionModel clientSession = accessCode.getClientSession(); - UserSessionModel userSession = clientSession.getUserSession(); - UserModel user = userSession.getUser(); - - initEvent(clientSession); - - String totp = formData.getFirst("totp"); - String totpSecret = formData.getFirst("totpSecret"); - - LoginFormsProvider loginForms = session.getProvider(LoginFormsProvider.class).setUser(user); - if (Validation.isBlank(totp)) { - return loginForms.setError(Messages.MISSING_TOTP) - .setClientSessionCode(accessCode.getCode()) - .createResponse(RequiredAction.CONFIGURE_TOTP); - } else if (!CredentialValidation.validOTP(realm, totp, totpSecret)) { - return loginForms.setError(Messages.INVALID_TOTP) - .setClientSessionCode(accessCode.getCode()) - .createResponse(RequiredAction.CONFIGURE_TOTP); - } - - UserCredentialModel credentials = new UserCredentialModel(); - credentials.setType(realm.getOTPPolicy().getType()); - credentials.setValue(totpSecret); - session.users().updateCredential(realm, user, credentials); - - - // if type is HOTP, to update counter we execute validation based on supplied token - UserCredentialModel cred = new UserCredentialModel(); - cred.setType(realm.getOTPPolicy().getType()); - cred.setValue(totp); - session.users().validCredentials(realm, user, cred); - - user.setOtpEnabled(true); - - user.removeRequiredAction(RequiredAction.CONFIGURE_TOTP); - - event.clone().event(EventType.UPDATE_TOTP).success(); - - return AuthenticationManager.nextActionAfterAuthentication(session, userSession, clientSession, clientConnection, request, uriInfo, event); - } - @Path("email-verification") @GET public Response emailVerification(@QueryParam("code") String code, @QueryParam("key") String key) {