Skip to content

Commit

Permalink
SHIBUI-1994
Browse files Browse the repository at this point in the history
Bug fix and additional corrections
  • Loading branch information
chasegawa committed Jul 14, 2021
1 parent 401dbf9 commit 2ef26b2
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,13 @@ public User getCurrentUser() {
}
return user;
}

public Set<String> getUserRoles(String username) {
Optional<User> user = userRepository.findByUsername(username);
HashSet<String> result = new HashSet<>();
if (user.isPresent() ) {
user.get().getRoles().forEach(role -> result.add(role.getName()));
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import edu.internet2.tier.shibboleth.admin.ui.service.EmailService;

import org.apache.commons.lang3.RandomStringUtils;
import org.pac4j.core.context.JEEContext;
import org.pac4j.core.context.session.JEESessionStore;
import org.pac4j.core.matching.matcher.Matcher;
import org.pac4j.core.profile.CommonProfile;
import org.pac4j.saml.profile.SAML2Profile;
import org.slf4j.Logger;
Expand All @@ -24,6 +27,7 @@
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
Expand All @@ -40,12 +44,14 @@ public class AddNewUserFilter implements Filter {
private RoleRepository roleRepository;
private Pac4jConfigurationProperties.SAML2ProfileMapping saml2ProfileMapping;
private UserRepository userRepository;
private Matcher matcher;

public AddNewUserFilter(Pac4jConfigurationProperties pac4jConfigurationProperties, UserRepository userRepository, RoleRepository roleRepository, Optional<EmailService> emailService) {
public AddNewUserFilter(Pac4jConfigurationProperties pac4jConfigurationProperties, UserRepository userRepository, RoleRepository roleRepository, Matcher matcher, Optional<EmailService> emailService) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
this.emailService = emailService;
this.pac4jConfigurationProperties = pac4jConfigurationProperties;
this.matcher = matcher;
saml2ProfileMapping = this.pac4jConfigurationProperties.getSaml2ProfileMapping();
}

Expand Down Expand Up @@ -73,6 +79,10 @@ public void destroy() {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
JEEContext context = new JEEContext((HttpServletRequest)request, (HttpServletResponse)response);
if (!matcher.matches(context, JEESessionStore.INSTANCE)) {
return;
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
CommonProfile profile = (CommonProfile) authentication.getPrincipal();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,20 @@
import org.pac4j.saml.client.SAML2Client;
import org.pac4j.saml.config.SAML2Configuration;
import org.pac4j.saml.credentials.authenticator.SAML2Authenticator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;

import com.google.common.collect.Lists;

import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository;

import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService;
import lombok.extern.slf4j.Slf4j;

/**
Expand All @@ -38,6 +43,9 @@
public class Pac4jConfiguration {
public final static String PAC4J_CLIENT_NAME = "shibUIAuthClient";

@Autowired
private UserService userService;

/**
* Custom class that ensures we add the user's roles to the information when doing SAML2 auth
*/
Expand All @@ -52,6 +60,11 @@ public Config config(final Pac4jConfigurationProperties pac4jConfigProps,
log.info("**** Configuring PAC4J ");
final Config config = new Config();
final Clients clients = new Clients(pac4jConfigProps.getCallbackUrl());

// configure the matcher for bypassing auth checks
PathMatcher pm = new PathMatcher();
pm.setExcludedPaths(Lists.newArrayList("/favicon.ico", "/unsecured/**/*", "/assets/**/*.png", "/static/**/*"));
config.addMatcher("exclude-paths-matcher", pm);

// Configure the client
switch (pac4jConfigProps.getTypeOfAuth()) {
Expand Down Expand Up @@ -99,20 +112,25 @@ public void validate(Credentials credentials, WebContext context, SessionStore s
final CommonProfile profile = new CommonProfile();
String token = ((TokenCredentials)credentials).getToken();
profile.setId(token);
profile.setRoles(userService.getUserRoles(token));
credentials.setUserProfile(profile);
}
});
headerClient.setName(PAC4J_CLIENT_NAME);
clients.setClients(headerClient);
}
}

// configure the matcher for bypassing auth checks
PathMatcher pm = new PathMatcher();
pm.setExcludedPaths(Lists.newArrayList("/favicon.ico", "/unsecured/**/*", "/error", "/login", "/"));
config.addMatcher("exclude-paths-matcher", pm);

}
config.setClients(clients);
return config;
}

@Bean
public ErrorPageRegistrar errorPageRegistrar() {
return this::registerErrorPages;
}

private void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(HttpStatus.UNAUTHORIZED, "/unsecured/error.html"));
registry.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN, "/unsecured/error.html"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import org.apache.commons.lang3.StringUtils;
import org.pac4j.core.config.Config;
import org.pac4j.core.matching.matcher.Matcher;
import org.pac4j.core.matching.matcher.PathMatcher;
import org.pac4j.springframework.security.web.CallbackFilter;
import org.pac4j.springframework.security.web.SecurityFilter;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -60,23 +62,30 @@ public Pac4jWebSecurityConfigurerAdapter(final Config config, UserRepository use

@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**");
http.addFilterBefore(getFilter(config, pac4jConfigurationProperties.getTypeOfAuth()), BasicAuthenticationFilter.class);
http.addFilterAfter(new AddNewUserFilter(pac4jConfigurationProperties, userRepository, roleRepository, emailService), SecurityFilter.class);
http.authorizeRequests().anyRequest().fullyAuthenticated();
http.authorizeRequests().antMatchers("/unsecured/**/*").permitAll();

// add filter based on auth type
http.antMatcher("/**").addFilterBefore(getFilter(config, pac4jConfigurationProperties.getTypeOfAuth()), BasicAuthenticationFilter.class);

// add the new user filter
http.addFilterAfter(new AddNewUserFilter(pac4jConfigurationProperties, userRepository, roleRepository, getPathMatcher("exclude-paths-matcher") , emailService), SecurityFilter.class);

http.exceptionHandling().accessDeniedHandler((request, response, accessDeniedException) -> response.sendRedirect("/unsecured/error.html"));
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
http.csrf().disable();
http.headers().frameOptions().disable();
}

private Matcher getPathMatcher(String name) {
return config.getMatchers().get(name);
}

private Filter getFilter(Config config2, String typeOfAuth) {
switch (typeOfAuth) {
case "SAML2":
return new CallbackFilter(this.config);
case "HEADER":
final SecurityFilter securityFilterForHeader = new SecurityFilter(this.config,
Pac4jConfiguration.PAC4J_CLIENT_NAME);
final SecurityFilter securityFilterForHeader = new SecurityFilter(this.config, Pac4jConfiguration.PAC4J_CLIENT_NAME);
securityFilterForHeader.setMatchers("exclude-paths-matcher");
return securityFilterForHeader;
}
Expand All @@ -91,6 +100,9 @@ public void configure(org.springframework.security.config.annotation.web.builder
firewall.setAllowUrlEncodedSlash(true);
firewall.setAllowUrlEncodedDoubleSlash(true);
web.httpFirewall(firewall);

// These don't need to be secured
web.ignoring().antMatchers("/favicon.ico", "/unsecured/**/*", "/assets/**/*.png", "/static/**/*", "/**/*.css");
}
}

Expand Down
2 changes: 1 addition & 1 deletion ui/public/unsecured/error.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="icon" type="image/png" sizes="96x96" href="assets/favicon-96x96.png">
<link rel="stylesheet" type="text/css" href="static.css">
<link rel="stylesheet" type="text/css" href="/unsecured/static.css">
<base href="/">
</head>
<body>
Expand Down

0 comments on commit 2ef26b2

Please sign in to comment.