Skip to content

Commit

Permalink
adding implementation of authentication module for security question
Browse files Browse the repository at this point in the history
  • Loading branch information
skublik committed Jan 7, 2020
1 parent 7f33477 commit b04a017
Show file tree
Hide file tree
Showing 68 changed files with 2,729 additions and 242 deletions.
5 changes: 5 additions & 0 deletions build-system/pom.xml
Expand Up @@ -1267,6 +1267,11 @@
<artifactId>prettytime</artifactId>
<version>4.0.0.Final</version>
</dependency>
<dependency>
<groupId>com.github.openjson</groupId>
<artifactId>openjson</artifactId>
<version>1.0.10</version>
</dependency>

<!-- webjars -->
<dependency>
Expand Down
4 changes: 4 additions & 0 deletions gui/admin-gui/pom.xml
Expand Up @@ -733,6 +733,10 @@
<artifactId>asm</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.github.openjson</groupId>
<artifactId>openjson</artifactId>
</dependency>

<!-- TEST -->

Expand Down
Expand Up @@ -80,7 +80,7 @@
})
@Profile("!test")
@SpringBootConfiguration
@ComponentScan(basePackages = {"com.evolveum.midpoint.web.security.module.factory","com.evolveum.midpoint.gui","com.evolveum.midpoint.gui.api"}, basePackageClasses = {TextAreaPanelFactory.class, GuiComponentRegistryImpl.class})
@ComponentScan(basePackages = {"com.evolveum.midpoint.web.security.factory","com.evolveum.midpoint.gui","com.evolveum.midpoint.gui.api"}, basePackageClasses = {TextAreaPanelFactory.class, GuiComponentRegistryImpl.class})
@EnableScheduling
public class MidPointSpringApplication extends AbstractSpringBootApplication {

Expand Down
Expand Up @@ -9,27 +9,14 @@

import com.evolveum.midpoint.web.security.*;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.evolveum.midpoint.web.security.provider.InternalPasswordProvider;
import com.evolveum.midpoint.web.security.provider.PasswordProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.access.AccessDeniedHandler;

/**
* @author skublik
Expand Down Expand Up @@ -64,7 +51,7 @@ protected void configure(HttpSecurity http) throws Exception {
.and()
.formLogin().disable()
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(new MidpointRestAuthenticationEntryPoint())
.exceptionHandling().authenticationEntryPoint(new RestAuthenticationEntryPoint())
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);

Expand All @@ -77,7 +64,7 @@ protected AuthenticationManager authenticationManager() throws Exception {

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new InternalPasswordProvider());
auth.authenticationProvider(new PasswordProvider());
}
}

Expand Up @@ -24,7 +24,7 @@
import com.evolveum.midpoint.web.page.self.PageSelf;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;

@PageDescriptor(url = "/resetPassword", action = {
@PageDescriptor(url = PageResetPassword.URL, action = {
@AuthorizationAction(actionUri = PageSelf.AUTH_SELF_ALL_URI,
label = PageSelf.AUTH_SELF_ALL_LABEL,
description = PageSelf.AUTH_SELF_ALL_DESCRIPTION),
Expand All @@ -35,6 +35,7 @@ public class PageResetPassword extends PageAbstractSelfCredentials{

private static final long serialVersionUID = 1L;

public static final String URL = "/resetPassword";

public PageResetPassword() {
// TODO Auto-generated constructor stub
Expand Down
Expand Up @@ -63,7 +63,7 @@
import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType;


@PageDescriptor(url = "/securityquestions", permitAll = true)
@PageDescriptor(url = "/securityquestionsold", permitAll = true)
public class PageSecurityQuestions extends PageBase {
private static final long serialVersionUID = 1L;

Expand Down
Expand Up @@ -54,6 +54,8 @@ public void initResetPolicyDto(SecurityPolicyType securityPolicyType) throws Sch
return;
}



MailResetPolicyType mailResetPolicy = securityPolicyType.getCredentialsReset().getMailReset();
if (mailResetPolicy != null) {
this.resetMethod = ResetMethod.MAIL;
Expand Down
Expand Up @@ -8,7 +8,9 @@
package com.evolveum.midpoint.web.page.login;

import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.model.api.authentication.ModuleWebSecurityConfiguration;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.SecurityPolicyUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.CommonException;
import com.evolveum.midpoint.util.logging.Trace;
Expand All @@ -23,11 +25,12 @@
import com.evolveum.midpoint.web.page.forgetpassword.PageForgotPassword;
import com.evolveum.midpoint.web.security.MidPointApplication;
import com.evolveum.midpoint.web.security.util.SecurityUtils;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AuthenticationSequenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsPolicyType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.RegistrationsPolicyType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SecurityPolicyType;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.ajax.AjaxRequestTarget;
Expand Down Expand Up @@ -79,36 +82,52 @@ public String getObject() {
add(form);

BookmarkablePageLink<String> link = new BookmarkablePageLink<>(ID_FORGET_PASSWORD, PageForgotPassword.class);
OperationResult parentResult = new OperationResult(OPERATION_LOAD_RESET_PASSWORD_POLICY);
SecurityPolicyType securityPolicy = null;
try {
securityPolicy = getModelInteractionService().getSecurityPolicy(null, null, parentResult);
} catch (CommonException e) {
LOGGER.warn("Cannot read credentials policy: " + e.getMessage(), e);
}
SecurityPolicyType finalSecurityPolicy = securityPolicy;
link.add(new VisibleEnableBehaviour() {
private static final long serialVersionUID = 1L;

@Override
public boolean isVisible() {
OperationResult parentResult = new OperationResult(OPERATION_LOAD_RESET_PASSWORD_POLICY);

SecurityPolicyType securityPolicy = null;
try {
securityPolicy = getModelInteractionService().getSecurityPolicy(null, null, parentResult);
} catch (CommonException e) {
LOGGER.warn("Cannot read credentials policy: " + e.getMessage(), e);
}

if (securityPolicy == null) {
if (finalSecurityPolicy == null) {
return false;
}

CredentialsPolicyType creds = securityPolicy.getCredentials();
CredentialsPolicyType creds = finalSecurityPolicy.getCredentials();

// TODO: Not entirely correct. This means we have reset somehow configured, but not necessarily enabled.
if (creds != null
&& ((creds.getSecurityQuestions() != null
&& creds.getSecurityQuestions().getQuestionNumber() != null) || (securityPolicy.getCredentialsReset() != null))) {
&& creds.getSecurityQuestions().getQuestionNumber() != null) || (finalSecurityPolicy.getCredentialsReset() != null))) {
return true;
}

return false;
}
});
if (securityPolicy != null && securityPolicy.getCredentialsReset() != null
&& StringUtils.isNotBlank(securityPolicy.getCredentialsReset().getAuthenticationSequenceName())) {
AuthenticationSequenceType sequence = SecurityUtils.getSequenceByName(securityPolicy.getCredentialsReset().getAuthenticationSequenceName(), securityPolicy.getAuthentication());
if (sequence == null) {
throw new IllegalArgumentException("Couldn't find sequence with name " + securityPolicy.getCredentialsReset().getAuthenticationSequenceName());
}
if (sequence.getChannel() == null || StringUtils.isBlank(sequence.getChannel().getUrlSuffix())) {
throw new IllegalArgumentException("Sequence with name " + securityPolicy.getCredentialsReset().getAuthenticationSequenceName() + " doesn't contain urlSuffix");
}
link.add(AttributeModifier.replace("href", new IModel<String>() {
@Override
public String getObject() {
return "./" + ModuleWebSecurityConfiguration.DEFAULT_PREFIX_OF_MODULE + "/" + sequence.getChannel().getUrlSuffix();
}
}));
}
form.add(link);

AjaxLink<String> registration = new AjaxLink<String>(ID_SELF_REGISTRATION) {
Expand Down
Expand Up @@ -6,6 +6,8 @@
*/
package com.evolveum.midpoint.web.page.login;

import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.spring.injection.annot.SpringBean;

Expand Down Expand Up @@ -99,6 +101,19 @@ private void initResetCredentialsConfiguration() {
}

private SecurityPolicyType resolveSecurityPolicy() {
SecurityPolicyType securityPolicy = resolveSecurityPolicy(null);

if (securityPolicy == null) {
LOGGER.error("No security policy defined.");
getSession()
.error(createStringResource("PageSelfRegistration.securityPolicy.notFound").getString());
throw new RestartResponseException(PageLogin.class);
}

return securityPolicy;
}

protected SecurityPolicyType resolveSecurityPolicy(PrismObject<UserType> user) {
SecurityPolicyType securityPolicy = runPrivileged(new Producer<SecurityPolicyType>() {
private static final long serialVersionUID = 1L;

Expand All @@ -110,7 +125,7 @@ public SecurityPolicyType run() {
OperationResult result = new OperationResult(OPERATION_GET_SECURITY_POLICY);

try {
return getModelInteractionService().getSecurityPolicy(null, task, result);
return getModelInteractionService().getSecurityPolicy(user, task, result);
} catch (CommonException e) {
LOGGER.error("Could not retrieve security policy: {}", e.getMessage(), e);
return null;
Expand All @@ -120,13 +135,6 @@ public SecurityPolicyType run() {

});

if (securityPolicy == null) {
LOGGER.error("No security policy defined.");
getSession()
.error(createStringResource("PageSelfRegistration.securityPolicy.notFound").getString());
throw new RestartResponseException(PageLogin.class);
}

return securityPolicy;

}
Expand Down
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2010-2013 Evolveum
~
~ 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.
-->

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:wicket="http://wicket.apache.org">
<body>
<wicket:extend>

<div class="row">
<div class="col-md-offset-2 col-md-8 col-lg-offset-4 col-lg-4">
<div class="panel panel-default" style="margin-top: 120px;">
<div class="panel-body">

<form class="form-horizontal" action="ignore" wicket:id="mainForm">
<div class="form-group" wicket:id="staticLayout">
<label class="col-md-4 col-lg-4 control-label">
<wicket:message key="PageLogin.username"/>
</label>

<div class="col-md-8 col-lg-8">
<input name="username" type="text" class="form-control input-sm focus-username"
wicket:message="placeholder:PageLogin.username" wicket:id="username">
</div>
</div>

<div wicket:id="dynamicLayout">
<div wicket:id="dynamicForm"/>
</div>

<div class="pull-right" wicket:id="firstLevelButtons">
<a class="btn btn-default" wicket:id="back1"><wicket:message key="PageBase.button.back"/></a>
<a class="btn btn-primary" wicket:id="showQuestions"><wicket:message key="PageSecurityQuestions.showQuestions"/></a>
</div>

<div wicket:id="csrfField"/>
<input type="hidden" wicket:id="answer"/>
<input type="hidden" wicket:id="user"/>

<div class ="com-md-12" wicket:id="insideForm">
<h4><wicket:message key="PageSecurityQuestions.questions"/></h4>
<hr>
<div wicket:id="questions">
<label wicket:id="questionText"></label>
<div class="col-md-12" style="padding-right: 0px; padding-left: 0px; padding-bottom: 15px;">
<input name="answer" type="text" class="form-control input-sm"
wicket:message="placeholder:PageSecurityQuestions.answer" wicket:id="questionAnswer">
</div>
</div>
<div class="pull-right">
<a class="btn btn-default" wicket:id="back2"><wicket:message key="PageBase.button.back"/></a>
<input type="submit" class="btn btn-primary" wicket:message="value:PageBase.button.send"/>
</div>
</div>
</form>
</div>
</div>
</div>
</div>


<script type="text/javascript">
$(".focus-username").focus();
</script>

<wicket:remove>This css is used to hide sidebar menu</wicket:remove>
<style type="text/css">
.content-wrapper, .right-side, .main-footer {
margin-left: 0px;

-moz-transition: none;
-webkit-transition: none;
-o-transition: color 0 ease-in;
transition: none;
}
</style>
</wicket:extend>

</body>
</html>

0 comments on commit b04a017

Please sign in to comment.