Cannot resolve method 'authenticated' in 'RequestMatcherConfigurer' - spring

I'm trying to implement token revoke using Spring OAuth2. I created this endpoint:
#PostMapping("/oauth/revoke")
public ResponseEntity<String> revoke(#RequestParam Map<String, String> params) {
RevocationService revocationService = revocationServiceFactory
.create(params.get("token_type_hint"));
revocationService.revoke(params.get("token"));
return ResponseEntity.ok().build();
}
Github code
I tried to configure these permissions:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.requestMatchers().anyRequest().authenticated().and() //<-- Error here
.requestMatchers().antMatchers("/oauth/revoke").permitAll().and()
.httpBasic().and()
.and()
.httpBasic()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
}
I can successfully generate OAuth2 token but I get always Access denied usisng this request:
curl --location --request POST 'http://localhost:8080/oauth/revoke' \
--header 'Authorization: Basic YWRtaW46cXdlcnR5' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'token=.......' \
--data-urlencode 'token_type_hint=access_token'
Do you know how path /oauth/revoke should be properly configured to allow authenticated users only to use this path? I get error Cannot resolve method 'authenticated' in 'RequestMatcherConfigurer' when I tied to apply the above configuration

Related

Spring Security 6 configuration with multiple security configs

I'm trying to setup my Spring Boot 3.0 / Spring Security 6 app with multiple security configs.
only /oauth/token should use/allow/enforce basic auth
all other endpoints will use/allow/enforce bearer auth
The issue I'm running into is that if I send a GET request to /test with the header Authorization: Basic xxx the basic auth filter is still picking it up.
This is what I have so far. The bearer filter isn't implemented yet, but for the sake of this question, let's assume all other endpoints should be wide open instead. How can I get them to bypass the basic auth filter if a user passes in basic auth header?
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(CsrfConfigurer::disable)
.authorizeHttpRequests()
.requestMatchers("/oauth/token").authenticated()
.anyRequest().permitAll()
.and()
.httpBasic(Customizer.withDefaults());
return http.build();
}
Like this one:
private static final String[] RESOURCE_ARGS = new String[]{
"/test/**"
};
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.requestMatchers(RESOURCE_ARGS).permitAll();
http
.csrf(CsrfConfigurer::disable)
.authorizeHttpRequests()
.requestMatchers("/oauth/token").authenticated()
.anyRequest().permitAll()
.and()
.httpBasic(Customizer.withDefaults());
....
}

spring security permit all considering basic auth passed and validating it

I am doing POC on spring security recently and saw some strange behavior. API endpoint configured as permit all is authenticating the request if client calls this endpoint using basic auth.
Sample code:
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/health").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic().authenticationEntryPoint(entryPoint)
.and()
.csrf().disable()
.cors().and()
.formLogin().disable();
return http.build();
Calling using curl as below is giving error:
curl -X GET -u "user:password" -H Content-Type:application/json http://localhost:20000/health
Error:
{"responseCode":401,"responseStatus":"Unauthorized","errorMessage":["Not authorized to access"],"responseMsg":null}
And if called without and user and password in above curl command then it works and return the desired response.
Can anyone please suggest if this is correct behavior and how to override it.
Auth entrypoint implementation:
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint{
#Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
ResponseData responseData = new ResponseData();
responseData.setResponseStatus(HttpStatus.UNAUTHORIZED.getReasonPhrase());
responseData.setErrorMessage(new ArrayList<>(Arrays.asList("Not authorized to access")));
responseData.setResponseCode(HttpServletResponse.SC_UNAUTHORIZED);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
String jsonResponse = mapper.writeValueAsString(responseData);
PrintWriter printWriter = response.getWriter();
printWriter.append(jsonResponse);
printWriter.flush();
printWriter.close();
}
}
permitAll does not mean that there is no authentication, it just states that there will be no authorization checks for that endpoint. Therefore, if you have httpBasic enabled and send the credentials in the request, the credentials will be checked by the BasicAuthenticationFilter against your UserDetailsService.
I assume that your credentials are wrong and that's why you are receiving a 401.

How to pass OAuth2Authentication in rest controller

I'm trying to get a token using rest controller and AuthorizationServerTokenServices.
I want to send my OAuth2Authentication through my body:
this is my request:
POST /external/oauth/token HTTP/1.1
Host: localhost:9000
Authorization: Basic Y2xpZW5012345678901234==
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: ebec711e-dc8f-4abc-ab54cd-61ec1234567
username=x&password=x&grant_type=x&scope=read write
username=x&password=x&grant_type=x&scope=read write
is a raw and Text
and this is controller:
#RequestMapping(value = {"/external/oauth/token","/external/oauth/token"}, method=RequestMethod.POST ,consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE,MediaType.ALL_VALUE},
produces = {MediaType.APPLICATION_ATOM_XML_VALUE, MediaType.APPLICATION_JSON_VALUE,MediaType.ALL_VALUE})
public OAuth2AccessToken getAccessToken( OAuth2Authentication temp) {
///not important
}
When im trying to run this endpoint im getting null on the passing object(=temp)
I'm attaching my http configure:
#Override
public void configure(HttpSecurity http) throws Exception {
http
.userDetailsService(userDetailsService)
.authorizeRequests()
.antMatchers(
"/**/users/**"
, "/**/groups/**"
)
.authenticated()
.and()
.authorizeRequests()
.anyRequest().permitAll();
}
}

two authentication mechanism on a spring boot application (Basic & JWT)

I have a spring boot app, I have just finished implementing a stateless authentication/authorization module based on jwt.
This is how I configured my security module:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.csrf()
.disable()
.headers()
.frameOptions()
.disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/authenticate").permitAll()
.antMatchers("/api/**").authenticated()
.and()
.apply(securityConfigurerAdapter());
}
So basically if I want to access the url /api/jobs I get a 401 error unless I send the bearer token which I get after a succesfull authentication on /api/authenticate.
What I need to know is if it's possible to access /api/jobs without supplying the bearer token, using a basic http authentication with a login and passowrd
Yes, it's possible, just make sure you have:
http.httpBasic();
in your configuration. That builder also have other methods to configure the details for basic auth.

Match everything but some specific path with Java configuration - antMatchers

Base on this Answer, I'm trying to secure everything but the login page in my spring app.
So I'm using this Java configuration files for OAuth2
The extends for the ResourceServerConfigurerAdapter:
#Override
public void configure(final HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/**")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.antMatchers("/login")
.permitAll()
The extends for OAuth2SsoConfigurerAdapter {
#Override
public void match(RequestMatchers matchers) {
matchers.antMatchers("/login");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated()
}
So, what I looking for is to have a http 401 for every request but for /login.
If a login request is perform the #EnableOAuth2Sso annotation would be used to redirect it to the OAuth2 server.
Update 1
After changing the order of the filter ResourceServerConfigurerAdapter, the /login request is not found.
http
.requestMatchers()
.antMatchers("/**")
.and()
.authorizeRequests()
.antMatchers("/login")
.permitAll()
.anyRequest()
.authenticated()
This request would be Unauthorized because any token is provided
~/ http 401 Unauthorized (good)
~/resource http 401 Unauthorized (good)
But the login page is not found:
~/login http 404 Not Found (bad)
The correct functionality should be a http 302 redirection to the OAuth2 server when the ~/login is hit.

Resources