Skip to content
This repository was archived by the owner on Dec 20, 2025. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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 gate-oauth2/gate-oauth2.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ dependencies {
implementation "io.spinnaker.kork:kork-retrofit"
implementation "io.spinnaker.kork:kork-security"
implementation "org.apache.groovy:groovy-json"
implementation "org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure"
implementation "org.springframework.boot:spring-boot-starter-oauth2-client"
implementation "org.springframework.session:spring-session-core"

testImplementation "com.squareup.retrofit2:retrofit-mock"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,110 +15,54 @@
*/
package com.netflix.spinnaker.gate.security.oauth2;

import com.netflix.spectator.api.Registry;
import com.netflix.spinnaker.fiat.shared.FiatClientConfigurationProperties;
import com.netflix.spinnaker.gate.config.AuthConfig;
import com.netflix.spinnaker.gate.security.AllowedAccountsSupport;
import com.netflix.spinnaker.gate.security.SpinnakerAuthConfig;
import com.netflix.spinnaker.gate.security.oauth2.provider.SpinnakerProviderTokenServices;
import com.netflix.spinnaker.gate.services.CredentialsService;
import com.netflix.spinnaker.gate.services.PermissionService;
import com.netflix.spinnaker.gate.services.internal.Front50Service;
import java.util.HashMap;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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.autoconfigure.security.oauth2.resource.ResourceServerProperties;
import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
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.Conditional;
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.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.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.session.web.http.DefaultCookieSerializer;
import org.springframework.stereotype.Component;

@Configuration
@SpinnakerAuthConfig
@EnableWebSecurity
@EnableOAuth2Sso
@EnableConfigurationProperties
@ConditionalOnProperty(name = "security.oauth2.client.clientId")
@Slf4j
@SpinnakerAuthConfig
@Conditional(OAuthConfigEnabled.class)
public class OAuth2SsoConfig extends WebSecurityConfigurerAdapter {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

WebSecurityConfigurerAdapter is deprecated. Are there plans to move to something that's not?

Copy link
Copy Markdown
Contributor Author

@rahul-chekuri rahul-chekuri Mar 18, 2025

Choose a reason for hiding this comment

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

We plan to delete the Adapter from the gate as part of the springboot3 upgrade.


@Autowired private AuthConfig authConfig;
@Autowired private ExternalAuthTokenFilter externalAuthTokenFilter;
@Autowired private ExternalSslAwareEntryPoint entryPoint;
@Autowired private SpinnakerOAuth2UserInfoService customOAuth2UserService;
@Autowired private SpinnakerOIDCUserInfoService oidcUserInfoService;
@Autowired private DefaultCookieSerializer defaultCookieSerializer;

@Primary
@Bean
@ConditionalOnProperty(
prefix = "security.oauth2.resource.spinnaker-user-info-token-services",
name = "enabled",
havingValue = "true",
matchIfMissing = true)
public ResourceServerTokenServices spinnakerUserInfoTokenServices(
ResourceServerProperties sso,
UserInfoTokenServices userInfoTokenServices,
CredentialsService credentialsService,
OAuth2SsoConfig.UserInfoMapping userInfoMapping,
OAuth2SsoConfig.UserInfoRequirements userInfoRequirements,
PermissionService permissionService,
Front50Service front50Service,
Optional<SpinnakerProviderTokenServices> providerTokenServices,
AllowedAccountsSupport allowedAccountsSupport,
FiatClientConfigurationProperties fiatClientConfigurationProperties,
Registry registry) {
return new SpinnakerUserInfoTokenServices(
sso,
userInfoTokenServices,
credentialsService,
userInfoMapping,
userInfoRequirements,
permissionService,
front50Service,
providerTokenServices,
allowedAccountsSupport,
fiatClientConfigurationProperties,
registry);
}
@Autowired private ClientRegistrationRepository clientRegistrationRepository;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this get used anywhere?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

3e64fb6

removed here


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

http.exceptionHandling().authenticationEntryPoint(entryPoint);
http.addFilterBefore(
new BasicAuthenticationFilter(authenticationManager()),
UsernamePasswordAuthenticationFilter.class);
http.addFilterBefore(externalAuthTokenFilter, AbstractPreAuthenticatedProcessingFilter.class);
authConfig.configure(httpSecurity);
httpSecurity
.authorizeRequests(auth -> auth.anyRequest().authenticated())
.oauth2Login(
oauth2 ->
oauth2.userInfoEndpoint(
userInfo ->
userInfo
.userService(customOAuth2UserService)
.oidcUserService(oidcUserInfoService)));
}

/**
* 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")
@ConfigurationProperties("spring.security.oauth2.client.registration.user-info-mapping")
@Data
public static class UserInfoMapping {
private String email = "email";
Expand All @@ -130,32 +74,6 @@ public static class UserInfoMapping {
}

@Component
@ConfigurationProperties("security.oauth2.user-info-requirements")
@ConfigurationProperties("spring.security.oauth2.client.registration.user-info-requirements")
public static class UserInfoRequirements extends HashMap<String, String> {}

/**
* 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
@ConditionalOnProperty(name = "security.oauth2.client.client-id")
public static class ExternalSslAwareEntryPoint extends LoginUrlAuthenticationEntryPoint {
@Autowired private AuthorizationCodeResourceDetails details;

@Autowired
public ExternalSslAwareEntryPoint(OAuth2SsoProperties sso) {
super(sso.getLoginPath());
}

@Override
protected String determineUrlToUseForThisRequest(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception) {
final String uri = details.getPreEstablishedRedirectUri();
return uri != null
? uri
: super.determineUrlToUseForThisRequest(request, response, exception);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2025 OpsMx, 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 java.util.regex.Pattern;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.type.AnnotatedTypeMetadata;

@Slf4j
public class OAuthConfigEnabled implements Condition {
Comment thread
dbyron-sf marked this conversation as resolved.
private static final String SPRING_SECURITY_OAUTH2_REGEX =
"spring\\.security\\.oauth2\\.client\\.registration\\..*\\.client-id";
private static final Pattern SPRING_SECURITY_OAUTH2_PATTERN =
Pattern.compile(SPRING_SECURITY_OAUTH2_REGEX);

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
if (!(context.getEnvironment() instanceof ConfigurableEnvironment)) {
Comment thread
dbyron-sf marked this conversation as resolved.
return false;
}

ConfigurableEnvironment env = (ConfigurableEnvironment) context.getEnvironment();

for (PropertySource<?> propertySource : env.getPropertySources()) {
if (propertySource instanceof EnumerablePropertySource) {
for (String propertyName :
((EnumerablePropertySource<?>) propertySource).getPropertyNames()) {
if (SPRING_SECURITY_OAUTH2_PATTERN.matcher(propertyName).matches()) {
return true; // If any property matches, load the configuration
}
}
}
}
return false; // Skip configuration if no matching properties found
}
}
Loading