Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implemented common jwt auth filter #650

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
<dependency>
<groupId>org.ohdsi</groupId>
<artifactId>authenticator</artifactId>
<version>0.0.1-SNAPSHOT</version>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the last version of authenticator is 0.0.3-SNAPSHOT

<version>0.0.2-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import com.odysseusinc.arachne.portal.service.PasswordResetService;
import com.odysseusinc.arachne.portal.service.ProfessionalTypeService;
import com.odysseusinc.arachne.portal.service.UserService;
import org.ohdsi.authenticator.service.Authenticator;
import org.ohdsi.authenticator.service.authentication.Authenticator;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.RestController;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
import io.swagger.annotations.ApiOperation;
import org.apache.solr.client.solrj.SolrServerException;
import org.ohdsi.authenticator.model.UserInfo;
import org.ohdsi.authenticator.service.Authenticator;
import org.ohdsi.authenticator.service.authentication.Authenticator;
import org.pac4j.core.credentials.UsernamePasswordCredentials;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.http.client.utils.URIBuilder;
import org.apache.solr.client.solrj.SolrServerException;
import org.ohdsi.authenticator.service.Authenticator;
import org.ohdsi.authenticator.service.authentication.Authenticator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
import com.odysseusinc.arachne.portal.service.UserService;
import com.odysseusinc.arachne.portal.service.analysis.AnalysisService;
import com.odysseusinc.arachne.portal.service.submission.SubmissionService;
import org.ohdsi.authenticator.service.Authenticator;
import org.ohdsi.authenticator.service.authentication.Authenticator;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.web.bind.annotation.RestController;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.ohdsi.authenticator.service.authentication.Authenticator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanInitializationException;
Expand Down Expand Up @@ -131,6 +132,9 @@ public static LinkedHashMap<String, URI> urlToHostUrlMapConverter(List<String> p
@Autowired
protected UserDetailsService userDetailsService;

@Autowired
protected Authenticator authenticator;

@Autowired
public void configureAuthentication(
AuthenticationManagerBuilder authenticationManagerBuilder
Expand Down Expand Up @@ -187,9 +191,9 @@ public ArachnePasswordValidator passwordValidator() throws IOException {
}

@Bean
public AuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
public AuthenticationTokenFilter authenticationTokenFilterBean(Authenticator authenticator) throws Exception {

return new AuthenticationTokenFilter();
return new AuthenticationTokenFilter(authenticator);
}

@Bean
Expand Down Expand Up @@ -310,7 +314,7 @@ protected void configure(HttpSecurity http) throws Exception {

// Custom JWT based authentication
http.addFilterBefore(loginRequestFilter(), UsernamePasswordAuthenticationFilter.class);
http.addFilterBefore(authenticationTokenFilterBean(), LoginRequestFilter.class);
http.addFilterBefore(authenticationTokenFilterBean(authenticator), LoginRequestFilter.class);
// DataNode authentication
http.addFilterBefore(authenticationSystemTokenFilter(), AuthenticationTokenFilter.class);
http.addFilterBefore(hostfilter, AuthenticationSystemTokenFilter.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@
package com.odysseusinc.arachne.portal.config;

import com.odysseusinc.arachne.portal.model.IUser;
import com.odysseusinc.arachne.portal.model.User;
import com.odysseusinc.arachne.portal.service.BaseUserService;
import org.ohdsi.authenticator.service.Authenticator;
import org.ohdsi.authenticator.service.authentication.Authenticator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@

package com.odysseusinc.arachne.portal.model;

import com.google.common.base.Objects;
import com.google.common.base.MoreObjects;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.odysseusinc.arachne.portal.api.v1.dto.InvitationType;
import com.odysseusinc.arachne.portal.security.ArachnePermission;
import com.odysseusinc.arachne.portal.security.HasArachnePermissions;
Expand Down Expand Up @@ -317,7 +316,7 @@ public void postLoad() {
@Override
public String toString() {

return Objects.toStringHelper(this)
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("author", author != null ? author.getId() : null)
.add("submissionGroup", submissionGroup != null ? submissionGroup.getId() : null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

package com.odysseusinc.arachne.portal.model;

import com.google.common.base.Objects;
import com.google.common.base.MoreObjects;
import com.odysseusinc.arachne.commons.api.v1.dto.CommonAnalysisType;
import com.odysseusinc.arachne.portal.service.impl.breadcrumb.Breadcrumb;
import com.odysseusinc.arachne.portal.service.impl.breadcrumb.EntityType;
Expand Down Expand Up @@ -181,7 +181,7 @@ public void setAnalysisType(CommonAnalysisType analysisType) {
@Override
public String toString() {

return Objects.toStringHelper(this)
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("analysis", analysis != null ? analysis.getId() : null)
.add("author", author != null ? author.getId() : null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,83 +24,64 @@

import com.odysseusinc.arachne.portal.config.tenancy.TenantContext;
import com.odysseusinc.arachne.portal.model.security.ArachneUser;
import java.io.IOException;
import java.util.Objects;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.ohdsi.authenticator.exception.AuthenticationException;
import org.ohdsi.authenticator.service.Authenticator;
import org.ohdsi.authenticator.filter.JWTAuthenticationFilter;
import org.ohdsi.authenticator.service.authentication.Authenticator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.GenericFilterBean;

public class AuthenticationTokenFilter extends GenericFilterBean {

Logger log = LoggerFactory.getLogger(AuthenticationTokenFilter.class);
public class AuthenticationTokenFilter extends JWTAuthenticationFilter {

public static final String USER_REQUEST_HEADER = "Arachne-User-Request";
@Value("${arachne.token.header}")
private String tokenHeader;

@Autowired
private UserDetailsService userDetailsService;
@Autowired
private Authenticator authenticator;

public AuthenticationTokenFilter(Authenticator authenticator) {

super(authenticator);
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException, AuthenticationException {
protected String getToken(HttpServletRequest httpRequest) {

HttpServletRequest httpRequest = (HttpServletRequest) request;
try {
String authToken = httpRequest.getHeader(tokenHeader);
if (authToken == null && httpRequest.getCookies() != null) {
for (Cookie cookie : httpRequest.getCookies()) {
if (cookie.getName().equalsIgnoreCase(tokenHeader)) {
authToken = cookie.getValue();
}
String authToken = httpRequest.getHeader(tokenHeader);
if (Objects.isNull(authToken) && httpRequest.getCookies() != null) {
for (Cookie cookie : httpRequest.getCookies()) {
if (cookie.getName().equalsIgnoreCase(tokenHeader)) {
authToken = cookie.getValue();
}
}
if (authToken != null) {
String username = authenticator.resolveUsername(authToken);
String requested = httpRequest.getHeader(USER_REQUEST_HEADER);
if (requested != null && username != null && !Objects.equals(username, requested)) {
throw new BadCredentialsException("forced logout");
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
return authToken;
}

TenantContext.setCurrentTenant(((ArachneUser) userDetails).getActiveTenantId());
}
}
} catch (AuthenticationException | org.springframework.security.core.AuthenticationException ex) {
String method = httpRequest.getMethod();
if (!HttpMethod.OPTIONS.matches(method)) {
if (log.isDebugEnabled()) {
log.debug("Authentication failed", ex);
} else {
log.error("Authentication failed: {}, requested: {} {}", ex.getMessage(), method, httpRequest.getRequestURI());
}
}
@Override
protected void onSuccessAuthentication(HttpServletRequest httpRequest, UserDetails userDetails, AbstractAuthenticationToken authentication) {

String requested = httpRequest.getHeader(USER_REQUEST_HEADER);
String username = userDetails.getUsername();
if (requested != null && username != null && !Objects.equals(username, requested)) {
throw new BadCredentialsException("forced logout");
}
chain.doFilter(request, response);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
TenantContext.setCurrentTenant(((ArachneUser) userDetails).getActiveTenantId());
}

@Override
protected UserDetails getUserDetails(String username) {

return this.userDetailsService.loadUserByUsername(username);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.ohdsi.authenticator.service.authentication.Authenticator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
Expand Down Expand Up @@ -106,6 +107,8 @@ public static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private EntryPointUnauthorizedHandler unauthorizedHandler;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private Authenticator authenticator;

@Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
Expand Down Expand Up @@ -157,14 +160,14 @@ protected void configure(HttpSecurity http) throws Exception {
.antMatchers("/api*//**").authenticated()
.anyRequest().permitAll();
http
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
.addFilterBefore(authenticationTokenFilterBean(authenticator), UsernamePasswordAuthenticationFilter.class);

}

@Bean
public AuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
public AuthenticationTokenFilter authenticationTokenFilterBean(Authenticator authenticator) throws Exception {

return new AuthenticationTokenFilter();
return new AuthenticationTokenFilter(authenticator);
}

@Autowired
Expand Down