com.google.cloud.spring.autoconfigure.security.IapAuthenticationAutoConfiguration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spring-cloud-gcp-autoconfigure Show documentation
Show all versions of spring-cloud-gcp-autoconfigure Show documentation
Spring Framework on Google Cloud
/*
* Copyright 2017-2020 the original author or authors.
*
* 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
*
* https://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.google.cloud.spring.autoconfigure.security;
import com.google.cloud.spring.autoconfigure.core.GcpContextAutoConfiguration;
import com.google.cloud.spring.autoconfigure.core.environment.ConditionalOnGcpEnvironment;
import com.google.cloud.spring.core.GcpEnvironment;
import com.google.cloud.spring.core.GcpProjectIdProvider;
import com.google.cloud.spring.security.iap.AppEngineAudienceProvider;
import com.google.cloud.spring.security.iap.AudienceProvider;
import com.google.cloud.spring.security.iap.AudienceValidator;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtIssuerValidator;
import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
/**
* Autoconfiguration for extracting pre-authenticated user identity from Google Cloud IAP header.
*
* Provides:
*
*
* - a custom {@link BearerTokenResolver} extracting identity from {@code
* x-goog-iap-jwt-assertion} header
*
- an ES256 web registry-based JWT token decoder bean with the following standard validations:
*
* - Issue time
*
- Expiration time
*
- Issuer
*
- Audience (this validation is only enabled if running on AppEngine, or if a custom
* audience is provided through {@code spring.cloud.gcp.security.iap.audience} property)
*
*
*
* @since 1.1
*/
@AutoConfiguration
@ConditionalOnProperty(value = "spring.cloud.gcp.security.iap.enabled", matchIfMissing = true)
@ConditionalOnClass({AudienceValidator.class})
@AutoConfigureBefore(OAuth2ResourceServerAutoConfiguration.class)
@AutoConfigureAfter(GcpContextAutoConfiguration.class)
@EnableConfigurationProperties(IapAuthenticationProperties.class)
public class IapAuthenticationAutoConfiguration {
private static final Log LOGGER = LogFactory.getLog(IapAuthenticationAutoConfiguration.class);
@Bean
@ConditionalOnMissingBean
public BearerTokenResolver iatTokenResolver(IapAuthenticationProperties properties) {
return r -> r.getHeader(properties.getHeader());
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty("spring.cloud.gcp.security.iap.audience")
public AudienceProvider propertyBasedAudienceProvider(IapAuthenticationProperties properties) {
return properties::getAudience;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnGcpEnvironment({
GcpEnvironment.APP_ENGINE_FLEXIBLE,
GcpEnvironment.APP_ENGINE_STANDARD
})
public AudienceProvider appEngineBasedAudienceProvider(GcpProjectIdProvider projectIdProvider) {
return new AppEngineAudienceProvider(projectIdProvider);
}
@Bean
@ConditionalOnMissingBean
public AudienceValidator audienceValidator(AudienceProvider audienceProvider) {
return new AudienceValidator(audienceProvider);
}
@Bean
@ConditionalOnMissingBean(name = "iapJwtDelegatingValidator")
public DelegatingOAuth2TokenValidator iapJwtDelegatingValidator(
IapAuthenticationProperties properties, AudienceValidator audienceValidator) {
List> validators = new ArrayList<>();
validators.add(new JwtTimestampValidator());
validators.add(new JwtIssuerValidator(properties.getIssuer()));
validators.add(audienceValidator);
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Audience configured for IAP JWT validation: " + audienceValidator.getAudience());
}
return new DelegatingOAuth2TokenValidator<>(validators);
}
@Bean
@ConditionalOnMissingBean
public JwtDecoder iapJwtDecoder(
IapAuthenticationProperties properties,
@Qualifier("iapJwtDelegatingValidator") DelegatingOAuth2TokenValidator validator) {
NimbusJwtDecoder jwtDecoder =
NimbusJwtDecoder.withJwkSetUri(properties.getRegistry())
.jwsAlgorithm(SignatureAlgorithm.from(properties.getAlgorithm()))
.build();
jwtDecoder.setJwtValidator(validator);
return jwtDecoder;
}
}