keycloak-aplcache

totp refactor

8/21/2015 6:53:26 PM

Details

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 f1effe7..fc264f9 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">
-        <form action="${url.loginUpdateTotpUrl}" class="${properties.kcFormClass!}" id="kc-totp-settings-form" method="post">
+        <form action="${url.loginAction}" class="${properties.kcFormClass!}" id="kc-totp-settings-form" method="post">
             <div class="${properties.kcFormGroupClass!}">
                 <div class="${properties.kcLabelWrapperClass!}">
                     <label for="otp" class="${properties.kcLabelClass!}">${msg("loginTotpOneTime")}</label>
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 61b035a..82adf9b 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<String, String> 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 eea2499..edd9e6a 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<String, String> 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) {