Home > Enterprise >  How to enable OAuth on a specific endpoint using spring security
How to enable OAuth on a specific endpoint using spring security

Time:10-28

I am trying to familiarize myself with Spring Security, in particular migrating from Spring Security OAuth to Soring Security (as in the following example/guide https://github.com/spring-projects/spring-security/wiki/OAuth-2.0-Migration-Guide).

However, I am seeming to only get 403 Forbidden errors. I am accessing from Postman and am using my company's existing OAuth server. I am able to get a token from the auth server, so I know I have those credentials correct and I have verified what roles the OAuth user has.

I am using the following dependencies:

implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
implementation 'org.springframework.boot:spring-boot-starter-web'

This is the simple endpoint I am attempting to access:

@RestController
public class AppController
{
   @GetMapping("/hello")
    public String hello()
    {
        return "hello";
    }
}

This is my application.yml file:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          jwk-set-uri: <<company-website-here>>/uaa/oauth/token_keys

And this is my security configuration class:

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http.authorizeRequests()
                .antMatchers(HttpMethod.GET, "/hello").hasRole("MY_ROLE")
                .anyRequest().authenticated()
                .and()
                .oauth2ResourceServer().jwt();
    }
}

I can't seem to figure out why I seem to only get 403 errors. I have also tried adding @EnableWebSecurity to the security config class, but that didn't make a difference. Adding the auth server URL explicitly to the server and/or manually creating a JwtDecoder didn't do the trick either; it appears the url is being automatically picked up from the yml file, based on its property name.

I am trying to move away from using the org.springframework.security.oauth.boot dependency and ResourceServerConfigurerAdapter.

I had to add my own converter like so:

private static class JwtAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken>
    {
        private final Converter<Jwt, Collection<GrantedAuthority>> jwtGrantedAuthoritiesConverter;

        public JwtAuthenticationConverter()
        {
            this.jwtGrantedAuthoritiesConverter = jwt -> jwt
                    .getClaimAsStringList("authorities")
                    .stream()
                    .map(SimpleGrantedAuthority::new)
                    .collect(Collectors.toList());
        }

        @Override
        public final AbstractAuthenticationToken convert(@NonNull Jwt jwt)
        {
            Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
            return new JwtAuthenticationToken(jwt, authorities, jwt.getClaimAsString("client_id"));
        }
    }

Then had to add this to the main security config:

.jwtAuthenticationConverter(new JwtAuthenticationConverter());

CodePudding user response:

There may be a couple of things happening.

  1. As you're migrating to Spring Security 5, you may need to extract your authorities manually. Check this post and it's correct answer.

  2. You are using hasRole function and this will append "ROLE_" before your authority/role. So if the role on your JWT token is not ROLE_JWT_ROLE you should use hasTransaction.

  • Related