Skip to content

Commit

Permalink
Working version of OAuth2Token mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
pvannierop committed Jan 8, 2024
1 parent 0fd0d4f commit d700c8a
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 286 deletions.
87 changes: 62 additions & 25 deletions src/main/java/org/cbioportal/security/config/ApiSecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,61 +1,98 @@
package org.cbioportal.security.config;

import org.cbioportal.security.token.RestAuthenticationEntryPoint;
import org.cbioportal.security.token.oauth2.OAuth2AccessTokenRefreshFilter;
import org.cbioportal.security.token.TokenAuthenticationFilter;
import org.cbioportal.security.token.TokenAuthenticationSuccessHandler;
import org.cbioportal.service.DataAccessTokenService;
import org.cbioportal.utils.config.annotation.ConditionalOnProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;

@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 2)
@ConditionalOnProperty(name = "authenticate", havingValue = {"saml", "oauth2"})
@ConditionalOnProperty(name = "authenticate", havingValue = {"false", "noauthsessionservice"}, isNot = true)
public class ApiSecurityConfig {

// Add security filter chains that handle calls to the API endpoints.
// Different chains are added for the '/api' and legacy '/webservice.do' paths.
// Both are able to handle API tokens provided in the request.
// see: "Creating and Customizing Filter Chains" @ https://spring.io/guides/topicals/spring-security-architecture

// Only available when using OAuth2 authentication.
@Autowired(required = false)
private OAuth2AccessTokenRefreshFilter oAuth2AccessTokenRefreshFilter;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

@Autowired(required = false)
private DataAccessTokenService tokenService;

@Autowired(required = false)
private AuthenticationProvider tokenAuthenticationProvider;

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// FIXME - csrf should be enabled
.csrf(AbstractHttpConfigurer::disable)
// This filter chain only grabs requests to the '/api' path.
.securityMatcher("/api/**")
.securityMatcher("/api/**", "/webservice.do")
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(
"/api/swagger-resources/**",
"/api/swagger-ui.html",
"/api/health",
"/api/cache/**").permitAll()
.anyRequest().authenticated()
.requestMatchers(
"/api/swagger-resources/**",
"/api/swagger-ui.html",
"/api/health",
"/api/cache/**").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(sessionManagement -> sessionManagement.sessionFixation().none())
.exceptionHandling(exceptionHandling -> exceptionHandling
.authenticationEntryPoint(restAuthenticationEntryPoint())
);
if (oAuth2AccessTokenRefreshFilter != null) {
http
.addFilterAfter(oAuth2AccessTokenRefreshFilter, SecurityContextPersistenceFilter.class);
// When dat.method is not 'none' and a tokenService bean is present,
// the apiTokenAuthenticationFilter is added to the filter chain.
if (tokenService != null) {
http.apply(ApiTokenFilterDsl.tokenFilterDsl(tokenService));
}
return http.build();
}

@Autowired
public AuthenticationManagerBuilder buildAuthenticationManager(AuthenticationManagerBuilder authenticationManagerBuilder) {
if (tokenAuthenticationProvider != null) {
authenticationManagerBuilder.authenticationProvider(tokenAuthenticationProvider);
}
return http.build();
}
return authenticationManagerBuilder;
}

@Bean
public RestAuthenticationEntryPoint restAuthenticationEntryPoint() {
return new RestAuthenticationEntryPoint();
}


}


class ApiTokenFilterDsl extends AbstractHttpConfigurer<ApiTokenFilterDsl, HttpSecurity> {

private final DataAccessTokenService tokenService;

public ApiTokenFilterDsl(DataAccessTokenService tokenService) {
this.tokenService = tokenService;
}

@Override
public void configure(HttpSecurity http) {
AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
TokenAuthenticationSuccessHandler tokenAuthenticationSuccessHandler = new TokenAuthenticationSuccessHandler();
TokenAuthenticationFilter filter = new TokenAuthenticationFilter("/**", authenticationManager, tokenService);
filter.setAuthenticationSuccessHandler(tokenAuthenticationSuccessHandler);
http.addFilterAfter(filter, SecurityContextPersistenceFilter.class);
}

public static ApiTokenFilterDsl tokenFilterDsl(DataAccessTokenService tokenService) {
return new ApiTokenFilterDsl(tokenService);
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.Customizer;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
Expand All @@ -25,14 +24,15 @@
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
@EnableWebSecurity
@ConditionalOnProperty(value = "authenticate", havingValue = "saml")
Expand All @@ -43,11 +43,16 @@ public class Saml2SecurityConfig {

@Autowired(required = false)
private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;

@Autowired
public void configure(AuthenticationManagerBuilder builder) {
OpenSaml4AuthenticationProvider saml4AuthenticationProvider = new OpenSaml4AuthenticationProvider();
saml4AuthenticationProvider.setResponseAuthenticationConverter(rolesConverter());
builder.authenticationProvider(saml4AuthenticationProvider);
}

@Bean
public SecurityFilterChain samlFilterChain(HttpSecurity http) throws Exception {
OpenSaml4AuthenticationProvider authenticationProvider = new OpenSaml4AuthenticationProvider();
authenticationProvider.setResponseAuthenticationConverter(rolesConverter());
DefaultSecurityFilterChain build = http
// FIXME - csrf should be enabled
.csrf(AbstractHttpConfigurer::disable)
Expand All @@ -59,9 +64,7 @@ public SecurityFilterChain samlFilterChain(HttpSecurity http) throws Exception {
new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), AntPathRequestMatcher.antMatcher("/api/**")
)
)
.saml2Login(saml2 -> saml2
.authenticationManager(new ProviderManager(authenticationProvider))
)
.saml2Login(withDefaults())
// NOTE: I did not get the official .saml2Logout() DSL to work as
// described at https://docs.spring.io/spring-security/reference/6.1/servlet/saml2/logout.html
// Logout Service POST Binding URL: http://localhost:8080/logout/saml2/slo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.stereotype.Component;

/**
*
* @author Manda Wilson
*/
public class TokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

@Autowired
private DataAccessTokenService tokenService;

private static final String BEARER = "Bearer";
Expand All @@ -70,7 +70,12 @@ public TokenAuthenticationFilter() {
public TokenAuthenticationFilter(String s, AuthenticationManager authenticationManagerBean) {
super(s, authenticationManagerBean);
}


public TokenAuthenticationFilter(String s, AuthenticationManager authenticationManager, DataAccessTokenService tokenService) {
super(s, authenticationManager);
this.tokenService = tokenService;
}

@Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
// only required if we do see an authorization header
Expand Down Expand Up @@ -118,4 +123,5 @@ protected String extractHeaderToken(HttpServletRequest request) {
}
return null;
}

}
Loading

0 comments on commit d700c8a

Please sign in to comment.