Ravi
Ravi

Reputation: 1

Spring Security - JOSE header typ application/okta-internal-at+jwt not allowed

I'm working with Spring Boot and Okta OAuth2 client integration using WebFlux. After configuring my dependencies and application properties, I encounter an issue with the JWT token validation. Specifically, I get an error where the JOSE header type application/okta-internal-at+jwt is not allowed.

The exception details are as follows: I have already tried to configure a custom ReactiveJwtDecoder with a custom token validator to handle Okta internal tokens. However, the validation fails due to the unsupported typ header in the JWT token (application/okta-internal-at+jwt). My expectation was that the custom validator would allow the token to pass, but it didn't.

pom.xml

Spring Boot Version <version>3.4.1</version>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        </dependency>       

Application Properties Configuraataions

# Octa Security
spring.security.oauth2.client.registration.okta.client-id=0oan0wkeiuzfUuHsw5d7
spring.security.oauth2.client.registration.okta.client-secret=uHLcvr9G8jT69Lmbxb_PoHJ7ltPeE5zd4PphpxrwNvD41gP7vHALXdF7CMMjdhr2
spring.security.oauth2.client.registration.okta.scope=openid, profile, email, offline_access
spring.security.oauth2.client.registration.okta.provider=okta
spring.security.oauth2.client.provider.okta.issuer-uri=https://dev-52900394.okta.com
spring.security.oauth2.client.registration.okta.redirect-uri=http://localhost:8093/login/oauth2/code/okta

SecurityConfig

package com.gateway.ApiGateway.security;

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

  @Bean
  public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity httpSecurity) {

      httpSecurity
              .authorizeExchange(exchanges -> exchanges
                      .anyExchange()
                      .authenticated()
              )
              .oauth2Login()
              .and()
              .oauth2ResourceServer()
              .jwt();

      return httpSecurity.build();
  }

    @Bean
    public ReactiveJwtDecoder jwtDecoder() {
        NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder
                .withJwkSetUri("https://dev-52900394.okta.com/oauth2/v1/keys")
                .build();

        // Custom JWT validator to allow Okta internal tokens
        OAuth2TokenValidator<Jwt> customValidator = jwt -> {
            String tokenType = (String) jwt.getHeaders().get("typ");

            if (!"application/okta-internal-at+jwt".equals(tokenType) && !"JWT".equals(tokenType)) {
                throw new JwtValidationException("Invalid token type", null);
            }

            // Apply default validators (expiry, signature, etc.)
            return JwtValidators.createDefault().validate(jwt);
        };

        jwtDecoder.setJwtValidator(customValidator);
        return jwtDecoder;
    }

    @Bean
    public ReactiveJwtAuthenticationConverter jwtAuthenticationConverter() {
        ReactiveJwtAuthenticationConverter converter = new ReactiveJwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(jwt -> {
            List<GrantedAuthority> authorities = ((List<String>) jwt.getClaims().getOrDefault("roles", List.of()))
                    .stream()
                    .map(SimpleGrantedAuthority::new)
                    .collect(Collectors.toList());

            return Flux.fromIterable(authorities);
        });
        return converter;
    }
}

I trid below curl in postman

curl --location 'http://172.17.80.1:8093/questions' \
--header 'Authorization: Bearer eyJraWQiOiJaWTdvNEk5YWpMSmtQeENJNTFEVVJaQ1NvaEEtZjNKdFNDOWtLd1pva2ZnIiwidHlwIjoiYXBwbGljYXRpb25cL29rdGEtaW50ZXJuYWwtYXQrand0IiwiYWxnIjoiUlMyNTYifQ.eyJ2ZXIiOjEsImp0aSI6IkFULm5UTDRlRUxBc1RPRUVqZ21HMFlRc2NFdEQwbUlveXdhbDRzeXd4ODJWWTgub2FyMndybTE3ZEFYdllkdHA1ZDciLCJpc3MiOiJodHRwczovL2Rldi01MjkwMDM5NC5va3RhLmNvbSIsImF1ZCI6Imh0dHBzOi8vZGV2LTUyOTAwMzk0Lm9rdGEuY29tIiwic3ViIjoicmF2aWRvYmFyaXlhOTUzN0BnbWFpLmNvbSIsImlhdCI6MTczODIxODc4NiwiZXhwIjoxNzM4MjIyMzg2LCJjaWQiOiIwb2FuMHdrZWl1emZVdUhzdzVkNyIsInVpZCI6IjAwdW4wd202NTRrb3NZRm5mNWQ3Iiwic2NwIjpbIm9wZW5pZCIsInByb2ZpbGUiLCJlbWFpbCIsIm9mZmxpbmVfYWNjZXNzIl0sImF1dGhfdGltZSI6MTczODIxODc4Mn0.m4VJTDqpCl64PbE9dGYtzKokrU7Gf82UHfbPcroyVx4bO_psuLAjgzIinbqhbuiVRfHlN-nLGLS7jzSwY6Gib5uE1Fo-ioxkq1TUs7_bOYOI82O2XMoIe8H970FeMqprSZVdXYPMfEx5JlFdGSbl6rkQ6OG9QRRfkCk-GeZpG5O5BzE1eb9vMwO09oHntKaruv0OQJrIFu2lK1wxtfVcSBkM7xeTAWqrCQmHmuEjrj58PJFXU0Ci5RZgX6Yipp5LS0IhR7YnDmowy64PPkc9D1hOOJDxuDivT_X7-OcLhOZbH4bOhegr52va79nmMxquJlOsnE56xNCcCLA72xo6Aw' \
--header 'Cookie: SESSION=928008dd-57a2-470a-9565-13e606aaeb5d'

I got below exception

org.springframework.security.oauth2.server.resource.InvalidBearerTokenException: Failed to validate the token
    at org.springframework.security.oauth2.server.resource.authentication.JwtReactiveAuthenticationManager.onError(JwtReactiveAuthenticationManager.java:79) ~[spring-security-oauth2-resource-server-6.4.2.jar:6.4.2]
    at reactor.core.publisher.Mono.lambda$onErrorMap$28(Mono.java:3848) ~[reactor-core-3.7.1.jar:3.7.1]
    at reactor.core.publisher.Mono.lambda$onErrorResume$30(Mono.java:3938) ~[reactor-core-3.7.1.jar:3.7.1]
    at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94) ~[reactor-core-3.7.1.jar:3.7.1]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) ~[netty-transport-4.1.116.Final.jar:4.1.116.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.116.Final.jar:4.1.116.Final]
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.116.Final.jar:4.1.116.Final]
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.116.Final.jar:4.1.116.Final]
    at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
Caused by: org.springframework.security.oauth2.jwt.BadJwtException: Failed to validate the token
    at org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder.createClaimsSet(NimbusReactiveJwtDecoder.java:295) ~[spring-security-oauth2-jose-6.4.2.jar:6.4.2]
    at org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder$JwkSetUriReactiveJwtDecoderBuilder.lambda$processor$13(NimbusReactiveJwtDecoder.java:449) ~[spring-security-oauth2-jose-6.4.2.jar:6.4.2]
    at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106) ~[reactor-core-3.7.1.jar:3.7.1]
    ... 232 common frames omitted
Caused by: com.nimbusds.jose.proc.BadJOSEException: JOSE header typ (type) application/okta-internal-at+jwt not allowed
    at com.nimbusds.jose.proc.DefaultJOSEObjectTypeVerifier.verify(DefaultJOSEObjectTypeVerifier.java:149) ~[nimbus-jose-jwt-9.37.3.jar:9.37.3]
    at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:341) ~[nimbus-jose-jwt-9.37.3.jar:9.37.3]
    at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:303) ~[nimbus-jose-jwt-9.37.3.jar:9.37.3]
    at org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder.createClaimsSet(NimbusReactiveJwtDecoder.java:292) ~[spring-security-oauth2-jose-6.4.2.jar:6.4.2]
    ... 234 common frames omitted

Upvotes: 0

Views: 11

Answers (0)

Related Questions