Giter Club home page Giter Club logo

Comments (15)

royclarkson avatar royclarkson commented on June 25, 2024

Thanks for the feedback! I built this because I had run into the same issue. I wanted a basic sample app that integrated all these features. Regarding Spring Forms, that's out of scope for my goals with this app, but @rwinch may be able to provide some guidance.

from spring-rest-service-oauth.

rwinch avatar rwinch commented on June 25, 2024

@kibbled If you can provide a more concrete example of what you have and what you are looking for I can certainly see if I can help.

from spring-rest-service-oauth.

kibbled avatar kibbled commented on June 25, 2024

Basically this added to the working sample from this repo:

@Configuration
@EnableWebSecurity
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests().antMatchers("/app/**", "/css/**", "/img/**", "/js/**", "/bower_components/**").permitAll().and()
            .formLogin().loginPage("/login").permitAll().and()
            .logout().permitAll().and()
            .authorizeRequests().anyRequest().fullyAuthenticated();//.and()
        http.httpBasic();
        http.csrf().disable();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("username").password("mypass").roles("USER", "ADMIN");
    }
}

from spring-rest-service-oauth.

philippeboyd avatar philippeboyd commented on June 25, 2024

I'm facing the same problem. Currently working on a website that has a fully working WebSecurityConfig like @kibbled with datasource and what not.

I can't find a way to make it work with a ResourceServerConfigurerAdapter because :

in general (like with other Security configurers), if more than one configures the same preoperty, then the last one wins.
Taken from org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurer.class

This is my OAuth2ServerConfiguration class :

@Configuration
public class OAuth2ServerConfiguration {

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        private static final String RESOURCE_ID = "restservice";

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            // @formatter:off
            resources.resourceId(RESOURCE_ID);
            // @formatter:on
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            // @formatter:off
            // http.authorizeRequests().anyRequest().authenticated();
            http.authorizeRequests().antMatchers("/api/**").authenticated();
            // @formatter:on
        }

    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { /*...*/ }

Still trying to find a way to integrate both of them so that a user can login on the website www.example.com/login and still be able to send his token via an Android/iOS mobile app for REST calls to the server at www.example.com/api/getSomething.

I'm able to do one or the other but not both in the same project. Do I have to create a seperate project for my RESTful web services?

from spring-rest-service-oauth.

mariubog avatar mariubog commented on June 25, 2024

I think the issue is if two HttpSecurity configuartions are for the same path , otherwise if they are configured for different endpoints they work fine

from spring-rest-service-oauth.

mariubog avatar mariubog commented on June 25, 2024

Two working configurations:

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            // @formatter:off
            resources
                .resourceId(RESOURCE_ID);
            // @formatter:on
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            // @formatter:off
             http
                .requestMatchers()
                .antMatchers("/resources/**","/greeting")
                .and() 
                .authorizeRequests()
                .antMatchers("/resources").access("#oauth2.hasScope('read') or hasRole('ROLE_USER')")
                .antMatchers("/greeting").access("#oauth2.hasScope('read')"); 
            }

    }

and

    @Configuration
    @EnableWebSecurity
    @EnableWebMvcSecurity
     public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);

    }

    @Override
    @Bean
    @Qualifier("authenticationManagerBean")
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
          .authorizeRequests()
          .antMatchers( "/user")
           .authenticated()
           .antMatchers("/**").access("hasRole('ROLE_ADMIN')") 
           .and()
           .csrf().disable().formLogin();


    }
   }

works as desired, I added above to the spring-rest-service-oauth from this git, if it still does not work I can upload whole thing to github,
apparently they both cant work together unless in your oauth config you specify directly
.requestMatchers().antMatchers("/resources/**","/greeting") as you see above.
If you dont add that, configuration from WebSecurityConfigurerAdapter is completly ignored and I am not sure why, smeone could clear it up if possible, I would assume it might override it with defult security config, but it is not happening and endpoints specified for HttpSecurity in WebSecurityConfigurerAdapter suddenly dont require authentication at all, so you have to specify directly the range for this oauth security endpoints as above

btw could someone tell me how to color code so it looks nice like yours

from spring-rest-service-oauth.

philippeboyd avatar philippeboyd commented on June 25, 2024

Hi @mariubog,

thanks for your reply! I'll give it a try later today. You can add java after the ``` when you wrap your code.

```java
   // code for coloring
```
```html
   // code for coloring
```
```js
   // code for coloring
```
```css
   // code for coloring
```
// etc.

from spring-rest-service-oauth.

mariubog avatar mariubog commented on June 25, 2024

I think the problem has to do with the filter chains, when we create above two, web security configuration and oauth configuration we get three filter chains :

1First filter chain it is default filter chain only difference between other two is that it uses BasicAuthenticationFilter this are the matchers patterns it uses:
[ OrRequestMatcher [requestMatchers=[Ant [pattern='/oauth/token'], Ant [pattern='/oauth/token_key'], Ant [pattern='/oauth/check_token']]]

2 Second filter chain is the one that is our concern I guess, the difference from above is that it uses OAuth2AuthenticationProcessingFilter in place of BasicAuthenticationFilter
Now If I include .requestMatchers() .antMatchers("/resources/**","/greeting")
in above example these are the paterns:
[ OrRequestMatcher [requestMatchers=[Ant [pattern='/resources/**'], Ant [pattern='/greeting']]]
which pretty much narrows it down
but if I dont include those lines then org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfiguration$NotOAuthRequestMatcher object is used and it contains 5 following patterns:

        key "/oauth/authorize" (id=339) 
        key "/oauth/token" (id=334) 
        key "/oauth/error" (id=329) 
        key "/oauth/check_token" (id=325)   
        key "/oauth/confirm_access" (id=321)

and the method used for checking against patterns is:

                @Override
                public boolean matches(HttpServletRequest request) {
                    String requestPath = getRequestPath(request);
                    for (String path : mapping.getPaths()) {
                        if (requestPath.startsWith(path)) {
                            return false;
                        }
                    }
                    return true;
                } 

from ResourceServerConfiguration$NotOAuthRequestMatcher so if we are trying to acces path for example /user and obvoisly /user does not start with any of the 5 above patterns then the filter is executed. I guess it is NotOAuthRequestMatcher so it is supposed to do that but it still assuers selection of the filter chain that contains OAuth2AuthenticationProcessingFilter and oauth configuration. And no other filter after that will have any chance to be activated. In our case the third filter that authenticates against rules in the web security configuration.
So it is only a matter of the order of the filter chains in filter chain proxy that determins that we end up with Oauth autorization app wide rather than reaching web security configuration that we also specified.
Perhaps someone could confirm this because I am little confsed with this

3 this is the third filter chain that is last and has obviously widest range
org.springframework.security.web.util.matcher.AnyRequestMatcher@1
it uses UsernamePasswordAuthenticationFilter
it is the filter that would otherwise be used if filter number 2 was not selected

from spring-rest-service-oauth.

philippeboyd avatar philippeboyd commented on June 25, 2024

Ok so it's working with your solution! I think I understand now... By using the following in the ResourceServerConfiguration extends ResourceServerConfigurerAdapter

@Override
public void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http
        .requestMatchers().antMatchers("/api/**")
    .and() 
        .authorizeRequests().antMatchers("/api/**").access("#oauth2.hasScope('read') and hasRole('ROLE_USER')");
    // @formatter:on
}

I'm able to use web security and Oauth security for the path /api/**

I'm pretty sure it's because when it calls configure(HttpSecurity http) it gets the same HttpSecurity object (singleton I presume) and continues the configuration... so by adding matchers and giving them an .access("#oauth2.hasScope('read')") it doesn't override the previous web configurations that you did previously...

What I was trying before was that I reconfigured the whole think by adding in that method

.authorizeRequests().antMatchers("/api/**").authenticated()

So with this new .authenticated() it overrided my previous configuration in FormSecurityConfig extends WebSecurityConfigurerAdapter

from spring-rest-service-oauth.

mariubog avatar mariubog commented on June 25, 2024

I don think you can use both for the same path, it is the matter of the security filterchain selection so if they both use the same path it may be an issue, can you post both of your configurations?
and the HttpSecurity objects are different objects but it does not matter they are only configuration objects used to configure filter that does the job
and its requestMatchers() that narrows down your range for HttpSecurity otherwise it will be applied to all requests

from spring-rest-service-oauth.

philippeboyd avatar philippeboyd commented on June 25, 2024

This is my Web config

I also added an @order(Ordered.HIGHEST_PRECEDENCE) to my web configure(HttpSecurity) method to be sure my web config will load first.

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
protected static class FormSecurityConfig extends WebSecurityConfigurerAdapter {
    // code here

    @Override
    @Order(Ordered.HIGHEST_PRECEDENCE)
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
        .authorizeRequests().antMatchers("/paths/**","/for","/everyone","/here").permitAll()
        .and()
        .authorizeRequests().antMatchers("/paths/**","/for","/admin","/here").hasRole("ADMIN")
        .and()
        .authorizeRequests().antMatchers("/paths/**","/for","/anonymous","/here").anonymous()
        .anyRequest().authenticated()
        .and()
        .formLogin()
            .loginPage("/login")
            .loginProcessingUrl("/dologin")
            .successHandler(customAuthenticationSuccessHandler())
            .failureHandler(customAuthenticationFailureHandler())
            .authenticationDetailsSource(customAuthenticationDetailsSource())
            .permitAll()
        .and()
        .logout()
            .logoutUrl("/logout")
            .logoutSuccessHandler(customLogoutSuccessHandler())
            .deleteCookies("JSESSIONID");
        // @formatter:on
    }

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        @Autowired
        private TokenStore tokenStore;

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            resources.resourceId("id_here").tokenStore(tokenStore);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            // @formatter:off
            http
                .requestMatchers().antMatchers("/path_for_api/**")
            .and()
                .authorizeRequests().antMatchers("/path_for_api/**").access("#oauth2.hasScope('read') and hasRole('ROLE_USER')");
            // @formatter:on
        }

    }

}

from spring-rest-service-oauth.

mariubog avatar mariubog commented on June 25, 2024

Yup it works because you have different paths and they do not overlap

from spring-rest-service-oauth.

rwinch avatar rwinch commented on June 25, 2024

Sorry for being late to the party I have been on Holiday. It looks like you got this figured out though?

from spring-rest-service-oauth.

philippeboyd avatar philippeboyd commented on June 25, 2024

@rwinch yeah I got it working :) thanks!

from spring-rest-service-oauth.

royclarkson avatar royclarkson commented on June 25, 2024

@kibbled thanks for the original question! Seems like the issues have been worked through in the discussion. I'm closing this issue, but anyone feel free to submit a PR if you feel there is something useful to add to the app.

from spring-rest-service-oauth.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.