Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot2 Oauth2 Implicit Flow - http://localhost:8080/oauth/authorize getting Access Denied

I have created a Spring Boot 2 Application, integrated SpringFox Swagger 2.8.0 with Implicit Oauth2 Grant for Authentication and Authorization.

The Code is working fine but when I click Authorize button it redirects to the

http://localhost:8080/oauth/authorize?response_type=token&client_id=test-app-client-id&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fwebjars%2Fspringfox-swagger-ui%2Foauth2-redirect.html&scope=read&state=U3VuIE9jdCAxNCAyMDE4IDIwOjQyOjUwIEdNVCswNTMwIChJbmRpYSBTdGFuZGFyZCBUaW1lKQ%3D%3D

but shows Access Denied like as shown below.

My complete project is available in GitHub

MainApplication.java

@EnableSwagger2
@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@RestController
public class MainApplication /*extends WebMvcConfigurerAdapter*/
{

    public static void main(String[] args)
    {
        SpringApplication.run(MainApplication.class, args);
    }

    @RequestMapping("/user")
    public Principal user(Principal user) {
        return user;
    }

    @Bean
    SecurityConfiguration security() {
      return SecurityConfigurationBuilder.builder()//<19>
          .clientId("test-app-client-id")
          .build();
    }

    @Bean
    SecurityScheme oauth() {
          List<GrantType> grantTypes = new ArrayList<>();
          ImplicitGrant implicitGrant = new ImplicitGrant(new LoginEndpoint("http://localhost:8080/oauth/authorize"),"access_code");
          grantTypes.add(implicitGrant);
          List<AuthorizationScope> scopes = new ArrayList<>();
          scopes.add(new AuthorizationScope("read","Read access on the API"));
        return new OAuthBuilder()
                .name("SECURITY_SCHEME_OAUTH2")
                .grantTypes(grantTypes)
                .scopes(scopes)
                .build();
    }

    @Bean
    public Docket docket()
    {
        return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage(getClass().getPackage().getName()))
            .paths(PathSelectors.any())
            .build()
            .securitySchemes(Collections.singletonList(oauth()))
            .apiInfo(generateApiInfo());
    }


    private ApiInfo generateApiInfo()
    {
        return new ApiInfo("Sample Service", "This service is to check Sample Service.", "Version 1.0",
            "Sample Service", "[email protected]", "Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0");
    }
}

enter image description here

Update 1

I have added the security and the passwordencoder configure suggested from @AlexanderPetrov. Things are working fine, when I add @EnableResourceServer my login screen is showing Full authentication is required to access this resource like as shown below

enter image description here

Can anyone please help me on this

like image 902
Alex Man Avatar asked Oct 14 '18 16:10

Alex Man


1 Answers

You need to do the following changes in your code

  1. Form login configuration is necessary for implicit flow.
  2. Also if we use implicit flow token will be generated through authorization url instead of token url. So you need to change "/oauth/token" to "oauth/authorize". configure method below

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/oauth/authorize").authenticated()
        .and()
        .authorizeRequests().anyRequest().permitAll()
        .and()
        .formLogin().permitAll()
        .and()
        .csrf().disable();
    }
    
  3. Add password encoder in SecurityConfig class and invoke it to encode user password in globalUserDetails method. Encoder is necessary because you use in memory passwords. So without password encoder application fails with an error:

    Encoded password does not look like BCrypt
    

Code fragment below

@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
    PasswordEncoder passwordEncoder = passwordEncoder();
    auth.inMemoryAuthentication().passwordEncoder(passwordEncoder()).
            withUser("bill").password(passwordEncoder.encode("abc123")).roles("ADMIN").and()
            .withUser("$2a$10$TT7USzDvMxMZvf0HUVh9p.er1GGnjNQzlcGivj8CivnaZf9edaz6C")
            .password("$2a$10$TT7USzDvMxMZvf0HUVh9p.er1GGnjNQzlcGivj8CivnaZf9edaz6C").roles("USER");
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

Hope it helps. I've created branch for your project but couldn't push it because of 403. So all necessary code is here in my answer.

like image 88
Alexander Petrov Avatar answered Sep 21 '22 03:09

Alexander Petrov