spring-projects / spring-projects/spring-security

Setting clock-skew according to documentation disables security features

Open
#18,230 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage type: enhancement
Dominant language
Java
Stars
9.6k
Forks
6.3k
Avg merge
2d 11h
Merged PRs (30d)
52

Description

Expected Behavior

I want to be able to set the clock-skew (ideally per property) and not change anything else.

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          clock-skew: 5m  # does not exist - would have been great

Current Behavior

According to OAuth 2.0 Resource Server JWT the correct way to do so is:

@Bean
JwtDecoder jwtDecoder() {
     NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder)
             JwtDecoders.fromIssuerLocation(issuerUri);

     OAuth2TokenValidator<Jwt> withClockSkew = new DelegatingOAuth2TokenValidator<>(
            new JwtTimestampValidator(Duration.ofSeconds(60)),
            new JwtIssuerValidator(issuerUri));

     jwtDecoder.setJwtValidator(withClockSkew);

     return jwtDecoder;
}

This works - but it is dangerous in my opinion. I also set the two (very important) properties

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: xxx
          jwk-set-uri: xxx

which triggers the auto configuration OAuth2ResourceServerJwtConfiguration

@Bean
@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.jwt.jwk-set-uri")
JwtDecoder jwtDecoderByJwkKeySetUri(ObjectProvider<JwkSetUriJwtDecoderBuilderCustomizer> customizers) {
	JwkSetUriJwtDecoderBuilder builder = NimbusJwtDecoder.withJwkSetUri(this.properties.getJwkSetUri())
		.jwsAlgorithms(this::jwsAlgorithms);
	customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
	NimbusJwtDecoder nimbusJwtDecoder = builder.build();
	String issuerUri = this.properties.getIssuerUri();
	OAuth2TokenValidator<Jwt> defaultValidator = (issuerUri != null)
			? JwtValidators.createDefaultWithIssuer(issuerUri) : JwtValidators.createDefault();
	nimbusJwtDecoder.setJwtValidator(getValidators(defaultValidator));
	return nimbusJwtDecoder;
}

If I understand it correctly, if I follow the documentation the JwtDecoder will NOT use the JwkSetUri property, the jwsAlgorithms and also not use the default validators. Both methods JwtValidators.createDefaultWithIssuer(issuerUri) : JwtValidators.createDefault(); will not only create the timestamp validator (and issuer validator if available) but also the X509CertificateThumbprintValidator (which is package visible btw). This one will also be missing if I configure the clock skew according to the documentation.

Context

What I implemented now is the following:

@Value("${xxx.jwt.clock-skew:PT5M}")
private Duration clockSkew;

@Bean
public BeanPostProcessor jwtDecoderClockSkewPostProcessor(final OAuth2ResourceServerProperties properties) {
    return new BeanPostProcessor() {
        @Override
        public Object postProcessAfterInitialization(@Nonnull final Object bean, @Nonnull final String beanName) {
            if (bean instanceof final NimbusJwtDecoder jwtDecoder) {
                jwtDecoder.setJwtValidator(createValidators(properties));
            }
            return bean;
        }
    };
}

private OAuth2TokenValidator<Jwt> createValidators(final OAuth2ResourceServerProperties properties) {
    final List<OAuth2TokenValidator<Jwt>> validators = new ArrayList<>();
    validators.add(new JwtTimestampValidator(clockSkew));

    final String issuerUri = properties.getJwt().getIssuerUri();
    if (issuerUri != null) {
        validators.add(new JwtIssuerValidator(issuerUri));
    }

    return JwtValidators.createDefaultWithValidators(validators);
}

My opinion:

  • The static methods at JwtValidators should maybe be replaced by a builder? That would have helped.
  • The auto configuration of the JwtDecoder seems hard to combine with other properties (like the clock-skew). Tapping into this configuration like I did was pretty tricky (until I arrived at the solution above).

Cheers,
Rainer

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with OAuth2ResourceServerJwtConfiguration and the JwtDecoder bean methods described in the issue, then inspect JwtValidators and the linked resource-server JWT documentation. Trace how issuer-uri, jwk-set-uri, jwsAlgorithms, and default validators are applied when customizing clock skew. Done means clock-skew can be configured without disabling those existing decoder settings and validators.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
authentication, security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.