Skip to content

Commit

Permalink
Issue Sunbird-Lern#24 chore:merged upstream/master
Browse files Browse the repository at this point in the history
  • Loading branch information
ahghatol committed Dec 27, 2017
2 parents 8f7929e + 5e2b8e6 commit d03285d
Show file tree
Hide file tree
Showing 11 changed files with 346 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.sunbird.keycloak.login.phone;

import org.jboss.logging.Logger;
import org.keycloak.authentication.AuthenticationFlowContext;
import org.keycloak.authentication.AuthenticationFlowError;
import org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages;
import org.sunbird.keycloak.resetcredential.sms.KeycloakSmsAuthenticatorConstants;

import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.util.List;

public abstract class AbstractPhoneFormAuthenticator extends AbstractUsernameFormAuthenticator {

private static final Logger logger = Logger.getLogger(AbstractPhoneFormAuthenticator.class);

public boolean validateUserAndPassword(AuthenticationFlowContext context, MultivaluedMap<String, String> inputData) {
String username = inputData.getFirst(AuthenticationManager.FORM_USERNAME);
logger.debug("AbstractPhoneFormAuthenticator@validateUserAndPassword - Username -" + username);

if (username == null) {
context.getEvent().error(Errors.USER_NOT_FOUND);
Response challengeResponse = invalidUser(context);
context.failureChallenge(AuthenticationFlowError.INVALID_USER, challengeResponse);
return false;
}

// remove leading and trailing whitespace
username = username.trim();

context.getEvent().detail(Details.USERNAME, username);
context.getAuthenticationSession().setAuthNote(AbstractPhoneFormAuthenticator.ATTEMPTED_USERNAME, username);

UserModel user = null;
try {
user = getUser(context, username);
} catch (ModelDuplicateException mde) {
ServicesLogger.LOGGER.modelDuplicateException(mde);

// Could happen during federation import
if (mde.getDuplicateFieldName() != null && mde.getDuplicateFieldName().equals(UserModel.EMAIL)) {
setDuplicateUserChallenge(context, Errors.EMAIL_IN_USE, Messages.EMAIL_EXISTS, AuthenticationFlowError.INVALID_USER);
} else {
setDuplicateUserChallenge(context, Errors.USERNAME_IN_USE, Messages.USERNAME_EXISTS, AuthenticationFlowError.INVALID_USER);
}

return false;
}

if (invalidUser(context, user)) {
return false;
}

if (!validatePassword(context, user, inputData)) {
return false;
}

if (!enabledUser(context, user)) {
return false;
}

String rememberMe = inputData.getFirst("rememberMe");
boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("on");
if (remember) {
context.getAuthenticationSession().setAuthNote(Details.REMEMBER_ME, "true");
context.getEvent().detail(Details.REMEMBER_ME, "true");
} else {
context.getAuthenticationSession().removeAuthNote(Details.REMEMBER_ME);
}
context.setUser(user);
return true;
}

private UserModel getUser(AuthenticationFlowContext context, String username) {
String numberRegex = "\\d+";
KeycloakSession session = context.getSession();

if (username.matches(numberRegex)) {
List<UserModel> userModels = session.users().searchForUserByUserAttribute(KeycloakSmsAuthenticatorConstants.ATTR_MOBILE, username, context.getRealm());

if (userModels != null && userModels.size() > 0) {
return userModels.get(0);
} else {
return KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), username);
}
} else {
return KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), username);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.sunbird.keycloak.login.phone;

import org.jboss.logging.Logger;
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
import org.keycloak.authentication.AuthenticationFlowContext;
import org.keycloak.authentication.AuthenticationProcessor;
import org.keycloak.authentication.Authenticator;
import org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.AuthenticationManager;

import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;

/**
* @author <a href="mailto:[email protected]">Bill Burke</a>
* @version $Revision: 1 $
*/
public class PhonePasswordForm extends AbstractPhoneFormAuthenticator implements Authenticator {
protected static ServicesLogger log = ServicesLogger.LOGGER;
private static final Logger logger = Logger.getLogger(PhonePasswordForm.class);

@Override
public void action(AuthenticationFlowContext context) {
logger.debug("PhonePasswordForm@action - called");
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
if (formData.containsKey("cancel")) {
context.cancelLogin();
return;
}
if (!validateForm(context, formData)) {
return;
}
context.success();
}

protected boolean validateForm(AuthenticationFlowContext context, MultivaluedMap<String, String> formData) {
logger.debug("PhonePasswordForm@validateForm - called");
return validateUserAndPassword(context, formData);
}

@Override
public void authenticate(AuthenticationFlowContext context) {
MultivaluedMap<String, String> formData = new MultivaluedMapImpl<>();
String loginHint = context.getAuthenticationSession().getClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM);

String rememberMeUsername = AuthenticationManager.getRememberMeUsername(context.getRealm(), context.getHttpRequest().getHttpHeaders());

if (loginHint != null || rememberMeUsername != null) {
if (loginHint != null) {
formData.add(AuthenticationManager.FORM_USERNAME, loginHint);
} else {
formData.add(AuthenticationManager.FORM_USERNAME, rememberMeUsername);
formData.add("rememberMe", "on");
}
}
Response challengeResponse = challenge(context, formData);
context.challenge(challengeResponse);
}

@Override
public boolean requiresUser() {
return false;
}

protected Response challenge(AuthenticationFlowContext context, MultivaluedMap<String, String> formData) {
LoginFormsProvider forms = context.form();

if (formData.size() > 0) forms.setFormData(formData);

return forms.createLogin();
}


@Override
public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
// never called
return true;
}

@Override
public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
// never called
}

@Override
public void close() {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.sunbird.keycloak.login.phone;

import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.authentication.Authenticator;
import org.keycloak.authentication.AuthenticatorFactory;
import org.keycloak.authentication.authenticators.browser.UsernamePasswordForm;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.provider.ProviderConfigProperty;

import java.util.List;

/**
* @author <a href="mailto:[email protected]">Bill Burke</a>
* @version $Revision: 1 $
*/
public class PhonePasswordFormFactory implements AuthenticatorFactory {

private static final Logger logger = Logger.getLogger(PhonePasswordFormFactory.class);

public static final String PROVIDER_ID = "auth-phone-password-form";
public static final PhonePasswordForm SINGLETON = new PhonePasswordForm();

@Override
public Authenticator create(KeycloakSession session) {
logger.debug("PhonePasswordFormFactory@create - PhonePasswordFormFactory is created");
return SINGLETON;
}

@Override
public void init(Config.Scope config) {

}

@Override
public void postInit(KeycloakSessionFactory factory) {

}

@Override
public void close() {

}

@Override
public String getId() {
return PROVIDER_ID;
}

@Override
public String getReferenceCategory() {
return UserCredentialModel.PASSWORD;
}

@Override
public boolean isConfigurable() {
return false;
}
public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
AuthenticationExecutionModel.Requirement.REQUIRED
};

@Override
public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
return REQUIREMENT_CHOICES;
}

@Override
public String getDisplayType() {
return "Phone Password Form";
}

@Override
public String getHelpText() {
return "Validates a phone and password from login form.";
}

@Override
public List<ProviderConfigProperty> getConfigProperties() {
return null;
}

@Override
public boolean isUserSetupAllowed() {
return false;
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sunbird.keycloak;
package org.sunbird.keycloak.resetcredential.sms;

import org.apache.http.util.TextUtils;
import org.jboss.logging.Logger;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sunbird.keycloak;
package org.sunbird.keycloak.resetcredential.sms;

/**
* Created by joris on 18/11/2016.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sunbird.keycloak;
package org.sunbird.keycloak.resetcredential.sms;

import org.jboss.logging.Logger;
import org.keycloak.common.util.Time;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sunbird.keycloak;
package org.sunbird.keycloak.resetcredential.sms;

import org.jboss.logging.Logger;
import org.keycloak.credential.CredentialProvider;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sunbird.keycloak;
package org.sunbird.keycloak.resetcredential.sms;

import org.jboss.logging.Logger;
import org.keycloak.Config;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sunbird.keycloak;
package org.sunbird.keycloak.resetcredential.sms;

import com.amazonaws.util.StringUtils;
import org.jboss.logging.Logger;
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
org.sunbird.keycloak.KeycloakSmsAuthenticatorFactory
org.sunbird.keycloak.resetcredential.sms.KeycloakSmsAuthenticatorFactory
org.sunbird.keycloak.login.phone.PhonePasswordFormFactory
Original file line number Diff line number Diff line change
@@ -1 +1 @@
org.sunbird.keycloak.KeycloakSmsAuthenticatorCredentialProviderFactory
org.sunbird.keycloak.resetcredential.sms.KeycloakSmsAuthenticatorCredentialProviderFactory

0 comments on commit d03285d

Please sign in to comment.