All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.spinnaker.gate.security.oauth2.OAuth2SsoConfig.groovy Maven / Gradle / Ivy

/*
 * Copyright 2016 Google, Inc.
 *
 * 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.
 */

package com.netflix.spinnaker.gate.security.oauth2

import com.netflix.spinnaker.gate.config.AuthConfig
import com.netflix.spinnaker.gate.security.SpinnakerAuthConfig
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2SsoProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
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.core.AuthenticationException
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter
import org.springframework.session.web.http.DefaultCookieSerializer
import org.springframework.stereotype.Component
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

@Configuration
@SpinnakerAuthConfig
@EnableWebSecurity
@EnableOAuth2Sso
@EnableConfigurationProperties
// Note the 4 single-quotes below - this is a raw groovy string, because SpEL and groovy
// string syntax overlap!
@ConditionalOnExpression(''''${security.oauth2.client.client-id:}'!=""''')
class OAuth2SsoConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  AuthConfig authConfig

  @Autowired
  ExternalAuthTokenFilter externalAuthTokenFilter

  @Autowired
  ExternalSslAwareEntryPoint entryPoint

  @Autowired
  DefaultCookieSerializer defaultCookieSerializer

  @Primary
  @Bean
  @ConditionalOnProperty(
    prefix = 'security.oauth2.resource.spinnaker-user-info-token-services',
    name = 'enabled',
    havingValue = 'true',
    matchIfMissing = true)
  ResourceServerTokenServices spinnakerUserInfoTokenServices() {
    new SpinnakerUserInfoTokenServices()
  }

  @Override
  void configure(HttpSecurity http) throws Exception {
    defaultCookieSerializer.setSameSite(null)
    authConfig.configure(http)

    http.exceptionHandling().authenticationEntryPoint(entryPoint)
    http.addFilterBefore(new BasicAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter)
    http.addFilterBefore(externalAuthTokenFilter, AbstractPreAuthenticatedProcessingFilter.class)
  }

  void configure(WebSecurity web) throws Exception {
    authConfig.configure(web)
  }

  /**
   * Use this class to specify how to map fields from the userInfoUri response to what's expected to be in the User.
   */
  @Component
  @ConfigurationProperties("security.oauth2.user-info-mapping")
  static class UserInfoMapping {
    String email = "email"
    String firstName = "given_name"
    String lastName = "family_name"
    String username = "email"
    String serviceAccountEmail = "client_email"
    String roles = null
  }

  @Component
  @ConfigurationProperties("security.oauth2.user-info-requirements")
  static class UserInfoRequirements extends HashMap {
  }

  /**
   * This class exists to change the login redirect (to /login) to the same URL as the
   * preEstablishedRedirectUri, if set, where the SSL is terminated outside of this server.
   */
  @Component
  @ConditionalOnExpression(''''${security.oauth2.client.client-id:}'!=""''')
  static class ExternalSslAwareEntryPoint extends LoginUrlAuthenticationEntryPoint {

    @Autowired
    private AuthorizationCodeResourceDetails details

    @Autowired
    ExternalSslAwareEntryPoint(OAuth2SsoProperties sso) {
      super(sso.loginPath)
    }

    @Override
    protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) {
      return details.preEstablishedRedirectUri ?: super.determineUrlToUseForThisRequest(request, response, exception)
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy