admin管理员组文章数量:1386692
I want to add a second authentication provider to my spring project but i'm using the Spring Boot Active Directory Starter dependency where i only configure the oauth2 resource server with a keyset uri and an authentication converter.
How would i approach this problem? Can i just add a second authentication provider or is some configuration needed for the aad auth before? If some configuration is needed could you explain this then to me?
Here is my current Spring Security Config
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SpringSecurityConfig implements WebMvcConfigurer {
@Value("${security.oauth2.resource.jwt.key-uri}")
private String keySetUri;
@Value("${security.oauth2.resource.id}")
private String resourceId;
@Value("${security.oauth2.issuer}")
private String issuer;
@Value("${security.oauth2.scope.access-as-user}")
private String accessAsUserScope;
private final FigaroAuthenticationConverter authenticationConverter;
@Autowired
public SpringSecurityConfig(FigaroAuthenticationConverter authenticationConverter) {
this.authenticationConverter = authenticationConverter;
}
/**
* Configures the security filter chain for the application.
*
* @param http the HttpSecurity to modify
* @return the configured SecurityFilterChain
* @throws Exception if an error occurs while configuring the filter chain
*/
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.cors(corsCustomizer ->
corsCustomizer.configurationSource(request -> {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("http://localhost:4200"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
config.setAllowCredentials(true);
config.setExposedHeaders(List.of("Authorization"));
config.setAllowedHeaders(List.of(
"Access-Control-Allow-Headers",
"Access-Control-Allow-Origin",
"Access-Control-Request-Method",
"Access-Control-Request-Headers",
"Origin",
"Cache-Control",
"Content-Type",
"Authorization"
));
config.setMaxAge(3600L);
return config;
}));
http.sessionManagement(Customizer.withDefaults())
.sessionManagement(sessionManagementConfigurer ->
sessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.oauth2ResourceServer(oauth2 ->
oauth2.jwt(jwtConfigurer -> {
jwtConfigurer.jwkSetUri(this.keySetUri);
jwtConfigurer.jwtAuthenticationConverter(jwtAuthenticationConverter());
}));
http.authorizeHttpRequests(auth -> {
auth.requestMatchers(HttpMethod.OPTIONS)
.permitAll();
auth.requestMatchers("/actuator/**", "/api-docs").permitAll();
auth.anyRequest().authenticated();
});
return http.build();
}
private JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(this.authenticationConverter);
return jwtAuthenticationConverter;
}
@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withJwkSetUri(this.keySetUri).build();
}
}
I havn't tried anything. But i don't really now where to start. I researched before this post a bit and found out that i could achive this with something like that
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(oAuth2ResourceServerConfigurer);
auth.authenticationProvider(customAuthenticationProvider);
}
----------------------- EDIT -----------------------
I've tried solving this issue with a request filter that is executed before the authentication filter. I thought i could authenticate it in the filter and proceed normally and it would skip the rest of the authentication but this didn't work they way i expected it.
public class ApiKeyAuthenticationFilter extends OncePerRequestFilter {
private static final String HEADER_NAME = "X-API-KEY";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
logger.info("Checking for API key");
String apiKey = request.getHeader(HEADER_NAME);
logger.info(apiKey);
if (StringUtils.hasText(apiKey)) {
Authentication auth = new ApiKeyAuthenticationToken(apiKey, List.of(new SimpleGrantedAuthority("ROLE_VIEWER")));
SecurityContextHolder.getContext().setAuthentication(auth);
return;
}
filterChain.doFilter(request, response);
}
}
As you can see i set the authentication and return immediatly. This raises now the issue that i get a status code 200 but no response body. This is because i return there, right?
The filter doesn't make very much sense for now, because i havn't added the "checking" part, but for now it is just for testing
I want to add a second authentication provider to my spring project but i'm using the Spring Boot Active Directory Starter dependency where i only configure the oauth2 resource server with a keyset uri and an authentication converter.
How would i approach this problem? Can i just add a second authentication provider or is some configuration needed for the aad auth before? If some configuration is needed could you explain this then to me?
Here is my current Spring Security Config
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SpringSecurityConfig implements WebMvcConfigurer {
@Value("${security.oauth2.resource.jwt.key-uri}")
private String keySetUri;
@Value("${security.oauth2.resource.id}")
private String resourceId;
@Value("${security.oauth2.issuer}")
private String issuer;
@Value("${security.oauth2.scope.access-as-user}")
private String accessAsUserScope;
private final FigaroAuthenticationConverter authenticationConverter;
@Autowired
public SpringSecurityConfig(FigaroAuthenticationConverter authenticationConverter) {
this.authenticationConverter = authenticationConverter;
}
/**
* Configures the security filter chain for the application.
*
* @param http the HttpSecurity to modify
* @return the configured SecurityFilterChain
* @throws Exception if an error occurs while configuring the filter chain
*/
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.cors(corsCustomizer ->
corsCustomizer.configurationSource(request -> {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("http://localhost:4200"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
config.setAllowCredentials(true);
config.setExposedHeaders(List.of("Authorization"));
config.setAllowedHeaders(List.of(
"Access-Control-Allow-Headers",
"Access-Control-Allow-Origin",
"Access-Control-Request-Method",
"Access-Control-Request-Headers",
"Origin",
"Cache-Control",
"Content-Type",
"Authorization"
));
config.setMaxAge(3600L);
return config;
}));
http.sessionManagement(Customizer.withDefaults())
.sessionManagement(sessionManagementConfigurer ->
sessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.oauth2ResourceServer(oauth2 ->
oauth2.jwt(jwtConfigurer -> {
jwtConfigurer.jwkSetUri(this.keySetUri);
jwtConfigurer.jwtAuthenticationConverter(jwtAuthenticationConverter());
}));
http.authorizeHttpRequests(auth -> {
auth.requestMatchers(HttpMethod.OPTIONS)
.permitAll();
auth.requestMatchers("/actuator/**", "/api-docs").permitAll();
auth.anyRequest().authenticated();
});
return http.build();
}
private JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(this.authenticationConverter);
return jwtAuthenticationConverter;
}
@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withJwkSetUri(this.keySetUri).build();
}
}
I havn't tried anything. But i don't really now where to start. I researched before this post a bit and found out that i could achive this with something like that
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(oAuth2ResourceServerConfigurer);
auth.authenticationProvider(customAuthenticationProvider);
}
----------------------- EDIT -----------------------
I've tried solving this issue with a request filter that is executed before the authentication filter. I thought i could authenticate it in the filter and proceed normally and it would skip the rest of the authentication but this didn't work they way i expected it.
public class ApiKeyAuthenticationFilter extends OncePerRequestFilter {
private static final String HEADER_NAME = "X-API-KEY";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
logger.info("Checking for API key");
String apiKey = request.getHeader(HEADER_NAME);
logger.info(apiKey);
if (StringUtils.hasText(apiKey)) {
Authentication auth = new ApiKeyAuthenticationToken(apiKey, List.of(new SimpleGrantedAuthority("ROLE_VIEWER")));
SecurityContextHolder.getContext().setAuthentication(auth);
return;
}
filterChain.doFilter(request, response);
}
}
As you can see i set the authentication and return immediatly. This raises now the issue that i get a status code 200 but no response body. This is because i return there, right?
The filter doesn't make very much sense for now, because i havn't added the "checking" part, but for now it is just for testing
Share Improve this question edited Mar 19 at 6:37 DasShorty asked Mar 18 at 13:44 DasShortyDasShorty 113 bronze badges 8 | Show 3 more comments1 Answer
Reset to default 0You can do this by creating a filter which implements the API Key style validation and adding it to the http filter chain. This will leave the oauth2 capability untouched.
This is a sample implementation from a current project:
@Service
@Slf4j
public class ApiKeyFilter extends GenericFilterBean {
public ApiKeyFilter(ApplicationProperties applicationProperties) {
try {
ourApiKey = applicationProperties.getCurata().getOurApiKey();
} catch (Exception e) {
log.error("Problems setting up api-key filter. Will not be able to authenticate Curata callbacks in spite of being indicated in the logs as ready for use");
ourApiKey = "nonesense";
}
}
public static final String API_KEY_HEADER = "X-API-Key";
private String ourApiKey;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String apiKey = resolveApiKey(httpServletRequest);
if (StringUtils.hasText(apiKey) && apiKey.equals(ourApiKey)) {
Authentication authentication = getAuthentication();
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(servletRequest, servletResponse);
}
private String resolveApiKey(HttpServletRequest request) {
String submittedApiKey = request.getHeader(API_KEY_HEADER);
if (StringUtils.hasText(submittedApiKey)) {
return submittedApiKey;
}
return null;
}
private Authentication getAuthentication() {
Collection<? extends GrantedAuthority> authorities = Arrays
.stream(new String[] {AuthoritiesConstants.CURATA})
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
User principal = new User("curata", "", authorities);
return new UsernamePasswordAuthenticationToken(principal, "from X-API-Key", authorities);
}
}
And add it to the http filter chain as follows:
@Component
@NoArgsConstructor
public class ApiKeyConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
@Autowired
ApplicationProperties applicationProperties;
@Override
public void configure(HttpSecurity http) {
ApiKeyFilter customFilter = new ApiKeyFilter(applicationProperties);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
本文标签: javaHow to add a second authentication provider for Spring Boot if i use Aad JwtsStack Overflow
版权声明:本文标题:java - How to add a second authentication provider for Spring Boot if i use Aad Jwts - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744509613a2609797.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
configure
method just configure and expose theAuthenticationProvider
as beans and they will be automatically be detected. – M. Deinum Commented Mar 18 at 14:33Authentication
object that works with your header. Based on theAuthentication
type the correctAuthenticationProvider
will be selected. – M. Deinum Commented Mar 19 at 7:23