001/*
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 *
006 *     http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * Unless required by applicable law or agreed to in writing, software
009 * distributed under the License is distributed on an "AS IS" BASIS,
010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011 * See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014package org.gbif.ws.remoteauth;
015
016import org.gbif.ws.remoteauth.app.GbifAppRemoteAuthenticationProvider;
017import org.gbif.ws.remoteauth.app.GbifAppRequestFilter;
018import org.gbif.ws.remoteauth.basic.BasicAuthRequestFilter;
019import org.gbif.ws.remoteauth.basic.BasicRemoteAuthenticationProvider;
020import org.gbif.ws.remoteauth.jwt.JwtRemoteBasicAuthenticationProvider;
021import org.gbif.ws.remoteauth.jwt.JwtRequestFilter;
022import org.gbif.ws.server.filter.HttpServletRequestWrapperFilter;
023import org.gbif.ws.server.filter.RequestHeaderParamUpdateFilter;
024
025import java.util.Arrays;
026import java.util.Collections;
027
028import org.springframework.context.ApplicationContext;
029import org.springframework.context.annotation.Bean;
030import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
031import org.springframework.security.config.annotation.web.builders.HttpSecurity;
032import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
033import org.springframework.security.config.http.SessionCreationPolicy;
034import org.springframework.security.web.csrf.CsrfFilter;
035import org.springframework.web.cors.CorsConfiguration;
036import org.springframework.web.cors.CorsConfigurationSource;
037import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
038
039/**
040 * Security Adapter that disables the authentication redirect and use GBIF remote services.
041 * Supports Basic and JWT authentication through JwtRemoteBasicAuthenticationProvider and
042 * JwtRemoteBasicAuthenticationProvider.
043 */
044public class RemoteAuthWebSecurityConfigurer extends WebSecurityConfigurerAdapter {
045
046  private final RemoteAuthClient remoteAuthClient;
047
048  public RemoteAuthWebSecurityConfigurer(
049      ApplicationContext context, RemoteAuthClient remoteAuthClient) {
050
051    setApplicationContext(context);
052    this.remoteAuthClient = remoteAuthClient;
053  }
054
055  @Override
056  protected void configure(AuthenticationManagerBuilder auth) {
057    auth.authenticationProvider(new BasicRemoteAuthenticationProvider(remoteAuthClient));
058    auth.authenticationProvider(new JwtRemoteBasicAuthenticationProvider(remoteAuthClient));
059    auth.authenticationProvider(new GbifAppRemoteAuthenticationProvider(remoteAuthClient));
060  }
061
062  @Override
063  protected void configure(HttpSecurity http) throws Exception {
064    http.authorizeRequests()
065        .anyRequest()
066        .permitAll()
067        .and()
068        .httpBasic()
069        .disable()
070        .addFilterAfter(
071            getApplicationContext().getBean(HttpServletRequestWrapperFilter.class),
072            CsrfFilter.class)
073        .addFilterAfter(
074            getApplicationContext().getBean(RequestHeaderParamUpdateFilter.class),
075            HttpServletRequestWrapperFilter.class)
076        .addFilterAfter(
077            new BasicAuthRequestFilter(authenticationManager()),
078            RequestHeaderParamUpdateFilter.class)
079        .addFilterAfter(new JwtRequestFilter(authenticationManager()), BasicAuthRequestFilter.class)
080        .addFilterAfter(new GbifAppRequestFilter(authenticationManager()), JwtRequestFilter.class)
081        .csrf()
082        .disable()
083        .cors()
084        .and()
085        .sessionManagement()
086        .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
087  }
088
089  /**
090   * Cors configuration, allows all methods and origins.
091   */
092  @Bean
093  CorsConfigurationSource corsConfigurationSource() {
094    // CorsFilter only applies this if the origin header is present in the request
095    CorsConfiguration configuration = new CorsConfiguration();
096    configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type"));
097    configuration.setAllowedOrigins(Collections.singletonList("*"));
098    configuration.setAllowedMethods(
099        Arrays.asList("HEAD", "GET", "POST", "DELETE", "PUT", "OPTIONS"));
100    configuration.setExposedHeaders(
101        Arrays.asList(
102            "Access-Control-Allow-Origin",
103            "Access-Control-Allow-Methods",
104            "Access-Control-Allow-Headers"));
105    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
106    source.registerCorsConfiguration("/**", configuration);
107    return source;
108  }
109}