I have a web application in React and backend in spring boot (2.7.0). Web application has two options for login, username/password and Azure AD popup. If username and password option is selected then authentication is done on my backend and JWT is generated and sent in response. If Azure AD option is selected then pop-up in shown (using MSAL library) and after successful login the JWT is also generated using MSAL library and used to fetch resources from my backend. On my backend I need to have an option to validate both JWT generated from that same backend and JWT generated from Azure AD. What is the best possible way to achieve that?
Here is my SecurityConfig
so far:
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private String jwkIssuerUri = "https://login.microsoftonline.com/xxxxxxxxxxxxx/v2.0";
@Autowired
JwtTokenValidator jwtTokenValidator;
private final CustomUserDetailsService userDetailsService;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http.cors(Customizer.withDefaults()).csrf().disable()
.authorizeRequests()
.antMatchers("/auth/authenticate")
.permitAll()
.anyRequest()
.authenticated()
.and()
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.oauth2ResourceServer(oauth -> oauth.jwt())
.exceptionHandling((ex) ->
ex.authenticationEntryPoint(
new BearerTokenAuthenticationEntryPoint())
.accessDeniedHandler(new BearerTokenAccessDeniedHandler())).build();
}
@Bean
public AuthenticationManager authenticationManager(UserDetailsService userDetailsService) {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return new ProviderManager(authProvider);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
JwtEncoder jwtEncoder() {
String key = "secret key";
return new NimbusJwtEncoder(new ImmutableSecret<>(key.getBytes()));
}
@Bean
JwtDecoder jwtDecoder() {
if(******* TO DO IF AZURE AD*******) {
NimbusJwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(this.jwkIssuerUri);
OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(this.jwkIssuerUri);
OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, this.jwtTokenValidator);
jwtDecoder.setJwtValidator(withAudience);
return jwtDecoder;
} else {
String key = "secret key"
byte[] bytes = key.getBytes();
SecretKeySpec originalKey = new SecretKeySpec(bytes, 0, bytes.length,"RSA");
return NimbusJwtDecoder.withSecretKey(originalKey).macAlgorithm(MacAlgorithm.HS512).build();
}
}
}
As you can see in jwtDecoder
, I'm not sure how to get different JwtDecoder
depending on the JWT that I need to validate.