Skip to content

Commit

Permalink
Add retry for JWT auth to avoid application startup failed
Browse files Browse the repository at this point in the history
  • Loading branch information
baixinsui committed Dec 9, 2024
1 parent 81a3df6 commit 8055052
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 23 deletions.
6 changes: 0 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
<springdoc.version>2.7.0</springdoc.version>
<checkstyle-maven-plugin.version>3.6.0</checkstyle-maven-plugin.version>
<logbook.version>3.10.0</logbook.version>
<nimbusds.oidc.sdk.version>11.20.1</nimbusds.oidc.sdk.version>
<lombok.version>1.18.30</lombok.version>
<opentelemetry.version>2.8.0</opentelemetry.version>
<eclipse.dash.tool.plugin>1.1.0</eclipse.dash.tool.plugin>
Expand Down Expand Up @@ -101,11 +100,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>oauth2-oidc-sdk</artifactId>
<version>${nimbusds.oidc.sdk.version}</version>
</dependency>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-spring-boot-starter</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* SPDX-License-Identifier: Apache-2.0
* SPDX-FileCopyrightText: Huawei Inc.
*
*/

package org.eclipse.xpanse.tofu.maker.security.oauth2.config;

import java.time.Duration;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.retry.support.RetrySynchronizationManager;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtDecoders;
import org.springframework.security.oauth2.jwt.JwtIssuerValidator;
import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;

/**
* Beans helper for creating JwtDecoder for OAuth2 JWT authentication.
*/
@Slf4j
@Configuration
public class Oauth2JwtDecoder {


/**
* Create JwtDecoder for OAuth2 JWT authentication.
*
* @param issuerUri url of the issuer.
* @return JwtDecoder.
*/
@Retryable(retryFor = Exception.class,
maxAttemptsExpression = "${http.request.retry.max.attempts}",
backoff = @Backoff(delayExpression = "${http.request.retry.delay.milliseconds}"))
public JwtDecoder createJwtDecoder(String issuerUri) {
int retryCount = Objects.isNull(RetrySynchronizationManager.getContext())
? 0 : RetrySynchronizationManager.getContext().getRetryCount();
log.info("Creating Oauth2 JwtDecoder from issuerUri:{}. Retry count:{}", issuerUri,
retryCount);
NimbusJwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(issuerUri);
OAuth2TokenValidator<Jwt> withClockSkew = new DelegatingOAuth2TokenValidator<>(
new JwtTimestampValidator(Duration.ofSeconds(60)),
new JwtIssuerValidator(issuerUri));
jwtDecoder.setJwtValidator(withClockSkew);
return jwtDecoder;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import static org.springframework.web.cors.CorsConfiguration.ALL;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.time.Duration;
import java.util.Collections;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
Expand All @@ -28,14 +28,7 @@
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;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtDecoders;
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.web.SecurityFilterChain;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
Expand Down Expand Up @@ -70,6 +63,9 @@ public class Oauth2WebSecurityConfig {
@Value("${spring.security.oauth2.resourceserver.opaquetoken.client-secret}")
private String clientSecret;

@Resource
private Oauth2JwtDecoder oauth2JwtDecoder;

/**
* Configures basic security handler per HTTP session.
*
Expand Down Expand Up @@ -145,14 +141,9 @@ CorsConfigurationSource corsConfigurationSource() {
}

@Bean
@ConditionalOnProperty("authorization.token.type")
@ConditionalOnProperty(name = "authorization.token.type", havingValue = "JWT")
JwtDecoder jwtDecoder() {
NimbusJwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(issuerUri);
OAuth2TokenValidator<Jwt> withClockSkew = new DelegatingOAuth2TokenValidator<>(
new JwtTimestampValidator(Duration.ofSeconds(60)),
new JwtIssuerValidator(issuerUri));
jwtDecoder.setJwtValidator(withClockSkew);
return jwtDecoder;
return oauth2JwtDecoder.createJwtDecoder(issuerUri);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
import org.springframework.security.oauth2.server.resource.introspection.NimbusOpaqueTokenIntrospector;
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
import org.springframework.security.oauth2.server.resource.introspection.SpringOpaqueTokenIntrospector;

/**
* Customize the OAuth2AuthoritiesOpaqueTokenIntrospector implements OpaqueTokenIntrospector.
Expand All @@ -30,7 +30,7 @@ public OauthOpaqueTokenIntrospector(String introspectionUri,
String clientId,
String clientSecret) {
opaqueTokenIntrospector =
new NimbusOpaqueTokenIntrospector(introspectionUri, clientId, clientSecret);
new SpringOpaqueTokenIntrospector(introspectionUri, clientId, clientSecret);
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ opentofu.root.module.directory=
clean.workspace.after.deployment.enabled=true
spring.retry.max-attempts=3
spring.retry.delay-millions=1000
support.default.opentofu.versions.only=true
opentofu.install.dir=/opt/opentofu
opentofu.download.base.url=https://github.com/opentofu/opentofu/releases
opentofu.versions=1.6.0,1.7.0,1.8.0
Expand Down

0 comments on commit 8055052

Please sign in to comment.